diff options
-rw-r--r-- | HISTORY.h | 11 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | configs/epg.dat | 2 | ||||
-rw-r--r-- | epg2vdr.c | 2 | ||||
-rw-r--r-- | lib/db.c | 102 | ||||
-rw-r--r-- | lib/db.h | 4 | ||||
-rw-r--r-- | lib/dbdict.h | 68 | ||||
-rw-r--r-- | lib/searchtimer.c | 74 | ||||
-rw-r--r-- | lib/searchtimer.h | 1 | ||||
-rw-r--r-- | menu.c | 9 | ||||
-rw-r--r-- | menu.h | 20 | ||||
-rw-r--r-- | menudone.c | 13 | ||||
-rw-r--r-- | menusched.c | 25 | ||||
-rw-r--r-- | menusearchtimer.c | 203 | ||||
-rw-r--r-- | parameters.c | 5 | ||||
-rw-r--r-- | po/de_DE.po | 62 | ||||
-rw-r--r-- | po/it_IT.po | 19 | ||||
-rw-r--r-- | status.c | 4 | ||||
-rw-r--r-- | timer.c | 25 |
19 files changed, 376 insertions, 277 deletions
@@ -5,8 +5,8 @@ * */ -#define _VERSION "1.1.92" -#define VERSION_DATE "07.03.2018" +#define _VERSION "1.1.93" +#define VERSION_DATE "09.03.2018" #define DB_API 6 @@ -19,8 +19,13 @@ /* * ------------------------------------ +2018-03-09 version 1.1.93 (horchi) + - added: Menu for matching 'jobs' (timersdone) of search timer results, with delete option + - added: some german translations + - added: optional (configurable) osd notification on timer change + 2018-03-07 version 1.1.92 (horchi) - - added: create of local switch timrt even when a 'recording' timer exists + - added: create of local switch timer even when a 'recording' timer exists 2018-02-26 version 1.1.91 (horchi) - change: backward compatibility to vdr 2.2.0 - another step @@ -2,6 +2,6 @@ - Fehler beim Anlegen eines Timer aus Suchergebniss, Dialog zeigt falschen Sender und File an - beim Timer löschen und laufender Aufnahme kommt dieser Hinweis nicht -- anlegen eines Suchtimer über das event -- timer mit action 'C' auch ohne vdruuid übernehmen - db Verbindungsdaten ohne Neustart übernehmen +- serien timer für gewählte Sendung erstellen + (anlegen eines Suchtimer über das event) diff --git a/configs/epg.dat b/configs/epg.dat index 8d3ce74..d98f882 100644 --- a/configs/epg.dat +++ b/configs/epg.dat @@ -396,7 +396,7 @@ Table useevents { CNTSOURCE "" cnt_source Ascii 10 Primary, CHANNELID "" cnt_channelid Ascii 50 Primary, - CNTEVENTID "" cnt_eventid UBigInt 0 Primary|Meta, + CNTEVENTID "" cnt_eventid UBigInt 0 Primary, MASTERID "" cnt_masterid UInt 0 Data|Meta, USEID "" cnt_useid UInt 0 Data, @@ -97,7 +97,7 @@ cEpgPluginMenu::cEpgPluginMenu(const char* title, cPluginEPG2VDR* aPlugin) { cOsdMenu::Add(new cOsdItem(hk(tr("Timer")), (eOSState)emsTimer)); cOsdMenu::Add(new cOsdItem(hk(tr("Search Timer")), (eOSState)emsSearchtimer)); - cOsdMenu::Add(new cOsdItem(hk(tr("Timer journal")), (eOSState)emsDones)); + cOsdMenu::Add(new cOsdItem(hk(tr("Timer Journal")), (eOSState)emsDones)); } cOsdMenu::Add(new cOsdItem(hk(tr("Program")), (eOSState)emsProgram)); @@ -13,6 +13,57 @@ #include "db.h" //*************************************************************************** +// Copy Values +//*************************************************************************** + +void cDbRow::copyValues(const cDbRow* rowFrom, int typesFilter) +{ + std::map<std::string, cDbFieldDef*>::iterator f; + + for (f = tableDef->dfields.begin(); f != tableDef->dfields.end(); f++) + { + cDbFieldDef* fld = f->second; + + if (rowFrom->isNull(fld)) // skip where source field is NULL + continue; + + if (!(typesFilter & fld->getType())) // Filter + continue; + + switch (fld->getFormat()) + { + case ffAscii: + case ffText: + case ffMText: + case ffMlob: + setValue(fld, rowFrom->getStrValue(fld)); + break; + + case ffFloat: + setValue(fld, rowFrom->getFloatValue(fld)); + break; + + case ffDateTime: + setValue(fld, rowFrom->getTimeValue(fld)); + break; + + case ffBigInt: + case ffUBigInt: + setBigintValue(fld, rowFrom->getBigintValue(fld)); + break; + + case ffInt: + case ffUInt: + setValue(fld, rowFrom->getIntValue(fld)); + break; + + default: + tell(0, "Fatal: Unhandled field type %d", fld->getFormat()); + } + } +} + +//*************************************************************************** // DB Statement //*************************************************************************** @@ -1310,57 +1361,6 @@ int cDbTable::checkIndex(const char* idxName, int& fieldCount) } //*************************************************************************** -// Copy Values -//*************************************************************************** - -void cDbTable::copyValues(cDbRow* r, int typesFilter) -{ - std::map<std::string, cDbFieldDef*>::iterator f; - - for (f = tableDef->dfields.begin(); f != tableDef->dfields.end(); f++) - { - cDbFieldDef* fld = f->second; - - if (r->isNull(fld)) // skip where source field is NULL - continue; - - if (!(typesFilter & fld->getType())) // Filter - continue; - - switch (fld->getFormat()) - { - case ffAscii: - case ffText: - case ffMText: - case ffMlob: - row->setValue(fld, r->getStrValue(fld)); - break; - - case ffFloat: - row->setValue(fld, r->getFloatValue(fld)); - break; - - case ffDateTime: - row->setValue(fld, r->getTimeValue(fld)); - break; - - case ffBigInt: - case ffUBigInt: - row->setBigintValue(fld, r->getBigintValue(fld)); - break; - - case ffInt: - case ffUInt: - row->setValue(fld, r->getIntValue(fld)); - break; - - default: - tell(0, "Fatal unhandled field type %d", fld->getFormat()); - } - } -} - -//*************************************************************************** // SQL Error //*************************************************************************** @@ -644,6 +644,8 @@ class cDbRow : public cDbService return s; } + void copyValues(const cDbRow* rFrom, int types = ftData); + virtual cDbFieldDef* getField(int id) { return tableDef->getField(id); } virtual cDbFieldDef* getField(const char* name) { return tableDef->getField(name); } virtual cDbFieldDef* getFieldByDbName(const char* dbname) { return tableDef->getFieldByDbName(dbname); } @@ -1133,7 +1135,7 @@ class cDbTable : public cDbService void setBigintValue(const char* n, int64_t value) { row->setBigintValue(n, value); } void setCharValue(const char* n, char value) { row->setCharValue(n, value); } - void copyValues(cDbRow* r, int types = ftData); + // void copyValues(cDbRow* r, int types = ftData); int hasValue(cDbFieldDef* f, const char* value) { return row->hasValue(f, value); } int hasCharValue(cDbFieldDef* f, char value) { return row->hasCharValue(f, value); } diff --git a/lib/dbdict.h b/lib/dbdict.h index 2999390..94aab67 100644 --- a/lib/dbdict.h +++ b/lib/dbdict.h @@ -25,10 +25,10 @@ typedef int (*FilterFromName)(const char* name); class _casecmp_ { public: - + bool operator() (const std::string& a, const std::string& b) const - { - return strcasecmp(a.c_str(), b.c_str()) < 0; + { + return strcasecmp(a.c_str(), b.c_str()) < 0; } }; @@ -85,7 +85,7 @@ class cDbService enum ProcType { - ptProcedure, + ptProcedure, ptFunction }; @@ -100,7 +100,7 @@ class cDbService static const char* formats[]; static const char* dictFormats[]; - static int toType(const char* type); + static int toType(const char* type); static const char* toName(FieldType type, char* buf); static TypeDef types[]; }; @@ -117,8 +117,8 @@ class cDbFieldDef : public cDbService friend class cDbDict; - cDbFieldDef() - { + cDbFieldDef() + { name = 0; dbname = 0, format = ffUnknown; @@ -131,7 +131,7 @@ class cDbFieldDef : public cDbService } cDbFieldDef(const char* n, const char* dn, FieldFormat f, int s, int t, int flt = 0xFFFF) - { + { name = strdup(n); dbname = strdup(dn); format = f; @@ -144,13 +144,13 @@ class cDbFieldDef : public cDbService } ~cDbFieldDef() { free(name); free(dbname); free(description); free(dbdescription); free(def); } - + int getIndex() { return index; } const char* getName() { return name; } int hasName(const char* n) { return strcasecmp(n, name) == 0; } int hasDbName(const char* n) { return strcasecmp(n, dbname) == 0; } - const char* getDescription() { return description; } - const char* getDbDescription() { return dbdescription; } + const char* getDescription() { return description; } + const char* getDbDescription() { return dbdescription; } const char* getDbName() { return dbname; } int getSize() { return size; } FieldFormat getFormat() { return format; } @@ -161,7 +161,7 @@ class cDbFieldDef : public cDbService int hasType(int types) { return types & type; } int hasFormat(int f) { return format == f; } - int isString() { return format == ffAscii || format == ffText || + int isString() { return format == ffAscii || format == ffText || format == ffMText || format == ffMlob; } int isInt() { return format == ffInt || format == ffUInt; } int isBigInt() { return format == ffBigInt || format == ffUBigInt; } @@ -178,9 +178,9 @@ class cDbFieldDef : public cDbService { if (!buf) return 0; - + sprintf(buf, "%s", toString(format)); - + if (format != ffMlob) { if (!size) @@ -192,16 +192,16 @@ class cDbFieldDef : public cDbService else if (format == ffFloat) size = 10; } - + if (format == ffFloat) sprintf(eos(buf), "(%d,%d)", size/10 + size%10, size%10); // 62 -> 8,2 else if (format == ffInt || format == ffUInt || format == ffBigInt || format == ffUBigInt || format == ffAscii) sprintf(eos(buf), "(%d)", size); - + if (format == ffUInt || format == ffUBigInt) sprintf(eos(buf), " unsigned"); } - + return buf; } @@ -216,16 +216,16 @@ class cDbFieldDef : public cDbService return yes; } - void show() - { - char colFmt[100]; + void show() + { + char colFmt[100]; char fType[100]; char tmp[100]; sprintf(fType, "(%s)", toName((FieldType)type, tmp)); - - tell(0, "%-20s %-25s %-17s %-20s (0x%04X) default '%s' '%s'", name, dbname, - toColumnFormat(colFmt), fType, filter, notNull(def, ""), description); + + tell(0, "%-20s %-25s %-17s %-20s (0x%04X) default '%s' '%s'", name, dbname, + toColumnFormat(colFmt), fType, filter, notNull(def, ""), description); } protected: @@ -270,7 +270,7 @@ class cDbIndexDef for (uint i = 0; i < dfields.size(); i++) s += dfields[i]->getName() + std::string(" "); - s.erase(s.find_last_not_of(' ')+1); + s.erase(s.find_last_not_of(' ')+1); tell(0, "Index %-25s (%s)", getName(), s.c_str()); } @@ -296,8 +296,8 @@ class cDbTableDef : public cDbService cDbTableDef(const char* n) { name = strdup(n); } - ~cDbTableDef() - { + ~cDbTableDef() + { for (uint i = 0; i < indices.size(); i++) delete indices[i]; @@ -307,17 +307,17 @@ class cDbTableDef : public cDbService clear(); } - const char* getName() { return name; } + const char* getName() { return name; } int fieldCount() { return dfields.size(); } cDbFieldDef* getField(int id) { return _dfields[id]; } - cDbFieldDef* getField(const char* fname, int silent = no) - { + cDbFieldDef* getField(const char* fname, int silent = no) + { std::map<std::string, cDbFieldDef*, _casecmp_>::iterator f; if ((f = dfields.find(fname)) != dfields.end()) return f->second; - + if (!silent) tell(0, "Fatal: Missing definition of field '%s.%s' in dictionary!", name, fname); @@ -325,7 +325,7 @@ class cDbTableDef : public cDbService } cDbFieldDef* getFieldByDbName(const char* dbname) - { + { std::map<std::string, cDbFieldDef*, _casecmp_>::iterator it; for (it = dfields.begin(); it != dfields.end(); it++) @@ -333,7 +333,7 @@ class cDbTableDef : public cDbService if (it->second->hasDbName(dbname)) return it->second; } - + tell(5, "Fatal: Missing definition of field '%s.%s' in dictionary!", name, dbname); return 0; @@ -362,7 +362,7 @@ class cDbTableDef : public cDbService { if (f->second) delete f->second; - + dfields.erase(f); } } @@ -422,7 +422,7 @@ class cDbDict : public cDbService dtFormat, dtSize, dtType, - + dtCount }; diff --git a/lib/searchtimer.c b/lib/searchtimer.c index 971230f..f0c32d5 100644 --- a/lib/searchtimer.c +++ b/lib/searchtimer.c @@ -911,65 +911,41 @@ int cSearchTimer::prepareDoneSelect(cDbRow* useeventsRow, int repeatfields, cDbS selectDoneTimer->build(" from %s where ", timersDoneDb->TableName()); // retry only 'F'ailed and re'J'ected timers, don't retry 'D'eleted timers sice they are deleted by user + /* + select id, state, title,comptitle, shorttext,compshorttext from timersdone where + state not in ('F','J') + and + (field('DERSTAATSANWALTDASLUDER', ifnull(comptitle,''),ifnull(episodecompshortname,'')) > 0 + or field('',ifnull(comptitle,''),ifnull(episodecompshortname,'NoShortnameAvailable')) > 0) + and + (field('',ifnull(compshorttext,''),ifnull(episodecomppartname,'')) > 0 + or field('',ifnull(compshorttext,''),ifnull(episodecomppartname,'')) > 0); + */ selectDoneTimer->build(" %s not in ('F','J')", // mysql ignoring case by default! timersDoneDb->getField("STATE")->getDbName()); - for (int i = 0; repeadCheckField[i]; i++) + if (repeatfields & sfTitle || repeatfields & sfFolge) // 'Folge' vergelichen und 'Titel' nicht macht keinen Sinn { - const char* fieldName = repeadCheckFieldName[i]; - - if (!timersDoneDb->getField(fieldName)) - tell(0, "AUTOTIMER: Search (for 'done' check) field '%s' not known!", - fieldName); - - else if (repeatfields & repeadCheckField[i]) - { - // specical handling for episode, use EPISODECOMPSHORTNAME instead (if not null)! - - if (repeadCheckField[i] == sfTitle) - { - if (!useeventsRow->getValue("EPISODECOMPSHORTNAME")->isNull()) - fieldName = "EPISODECOMPSHORTNAME"; - if (!useeventsRow->getValue("EPISODECOMPPARTNAME")->isNull()) - fieldName = "EPISODECOMPPARTNAME"; - } - - if (repeadCheckField[i] == sfFolge) - { - if (!useeventsRow->getValue("EPISODECOMPSHORTNAME")->isNull()) - fieldName = "EPISODECOMPSHORTNAME"; - } - - selectDoneTimer->bind(timersDoneDb->getField(fieldName), - cDBS::bndIn | cDBS::bndSet, " and "); + selectDoneTimer->build(" and (field('%s', ifnull(comptitle,''),ifnull(episodecompshortname,'')) > 0" + " or field('%s',ifnull(comptitle,''),ifnull(episodecompshortname,'NoShortnameAvailable')) > 0)", + useeventsRow->getStrValue("COMPTITLE"), useeventsRow->getStrValue("EPISODECOMPSHORTNAME")); + } - chkFields += " " + std::string(fieldName); - } + if (repeatfields & sfFolge) + { + selectDoneTimer->build(" and (field('%s',ifnull(compshorttext,'NoShortnameAvailable'),ifnull(episodecomppartname,'NoShortnameAvailable')) > 0" + " or field('%s',ifnull(compshorttext,'NoShortnameAvailable'),ifnull(episodecomppartname,'NoShortnameAvailable')) > 0)", + useeventsRow->getStrValue("COMPSHORTTEXT"), useeventsRow->getStrValue("EPISODECOMPPARTNAME")); } if (selectDoneTimer->prepare() != success) { - tell(0, "AUTOTIMER: Prepare of statement for 'done' check failed, skipping"); - return fail; + tell(0, "Error: AUTOTIMER: Prepare of statement for 'done' check failed, skipping"); + return yes; } timersDoneDb->clear(); - timersDoneDb->setValue("COMPTITLE", useeventsRow->getStrValue("COMPTITLE")); - - if (!useeventsRow->getValue("COMPSHORTTEXT")->isEmpty()) - timersDoneDb->setValue("COMPSHORTTEXT", useeventsRow->getStrValue("COMPSHORTTEXT")); - - if (!useeventsRow->getValue("EPISODECOMPNAME")->isEmpty()) - timersDoneDb->setValue("EPISODECOMPNAME", useeventsRow->getStrValue("EPISODECOMPNAME")); - if (!useeventsRow->getValue("EPISODECOMPSHORTNAME")->isEmpty()) - timersDoneDb->setValue("EPISODECOMPSHORTNAME", useeventsRow->getStrValue("EPISODECOMPSHORTNAME")); - - if (!useeventsRow->getValue("EPISODECOMPPARTNAME")->isEmpty()) - timersDoneDb->setValue("EPISODECOMPPARTNAME", useeventsRow->getStrValue("EPISODECOMPPARTNAME")); - - if (!useeventsRow->getValue("COMPLONGDESCRIPTION")->isEmpty()) - timersDoneDb->setValue("COMPLONGDESCRIPTION", useeventsRow->getStrValue("COMPLONGDESCRIPTION")); select = selectDoneTimer; @@ -1140,7 +1116,7 @@ int cSearchTimer::modifyCreateTimer(cDbRow* timerRow, int& newid) if (knownTimer) { - timerDb->copyValues(timerRow, cDBS::ftPrimary); + timerDb->getRow()->copyValues(timerRow, cDBS::ftPrimary); if (!timerDb->find()) { @@ -1176,7 +1152,7 @@ int cSearchTimer::modifyCreateTimer(cDbRow* timerRow, int& newid) // create new on other vdr - timerDb->copyValues(timerRow, cDBS::ftData); // takeover all data (can be modified by user) + timerDb->getRow()->copyValues(timerRow, cDBS::ftData); // takeover all data (can be modified by user) timerDb->setValue("ID", 0); timerDb->setCharValue("ACTION", taCreate); status += timerDb->insert(); @@ -1190,7 +1166,7 @@ int cSearchTimer::modifyCreateTimer(cDbRow* timerRow, int& newid) { // create 'C'reate oder 'M'odify request ... - timerDb->copyValues(timerRow, cDBS::ftData); + timerDb->getRow()->copyValues(timerRow, cDBS::ftData); timerDb->setCharValue("ACTION", knownTimer ? taModify : taCreate); diff --git a/lib/searchtimer.h b/lib/searchtimer.h index c99bc6b..07e841a 100644 --- a/lib/searchtimer.h +++ b/lib/searchtimer.h @@ -41,6 +41,7 @@ class cSearchTimer int prepareDoneSelect(cDbRow* useeventsRow, int repeatfields, cDbStatement*& select); cDbStatement* prepareSearchStatement(cDbRow* searchTimer, cDbTable* db); int matchCriterias(cDbRow* searchTimer, cDbRow* event); + cDbTable* getTimersDoneDb() { return timersDoneDb; } private: @@ -359,6 +359,7 @@ int cMenuDb::initDb() selectRecordingForEventByLv->build("select "); selectRecordingForEventByLv->bindAllOut(); + // selectRecordingForEventByLv->bindTextFree(", epglvr(title, ?)", recordingListDb->getValue("TITLE"), cDBS::bndIn); -> core :o selectRecordingForEventByLv->build(" from %s where ", recordingListDb->TableName()); selectRecordingForEventByLv->build(" (%s <> 'D' or %s is null)", recordingListDb->getField("STATE")->getDbName(), @@ -653,7 +654,7 @@ int cMenuDb::modifyTimer(cDbRow* timerRow, const char* destUuid, char destType) if (knownTimer) { timerDb->clear(); - timerDb->copyValues(timerRow, cDBS::ftPrimary); + timerDb->getRow()->copyValues(timerRow, cDBS::ftPrimary); if (!timerDb->find()) { @@ -678,7 +679,7 @@ int cMenuDb::modifyTimer(cDbRow* timerRow, const char* destUuid, char destType) // create new on other vdr - timerDb->copyValues(timerRow, cDBS::ftData); // takeover all data (can be modified by user) + timerDb->getRow()->copyValues(timerRow, cDBS::ftData); // takeover all data (can be modified by user) timerDb->setValue("ID", 0); // don't care on insert! timerDb->setValue("VDRUUID", destUuid); timerDb->setCharValue("ACTION", taCreate); @@ -693,7 +694,7 @@ int cMenuDb::modifyTimer(cDbRow* timerRow, const char* destUuid, char destType) { // create 'C'reate oder 'M'odify request ... - timerDb->copyValues(timerRow, cDBS::ftData); + timerDb->getRow()->copyValues(timerRow, cDBS::ftData); timerDb->setCharValue("ACTION", knownTimer ? taModify : taCreate); timerDb->getValue("STATE")->setNull(); @@ -766,7 +767,7 @@ int cMenuDb::createTimer(cDbRow* timerRow, const char* destUuid, int type) // Timer 'C'reate request ... timerDb->clear(); - timerDb->copyValues(timerRow, cDBS::ftData); + timerDb->getRow()->copyValues(timerRow, cDBS::ftData); timerDb->setValue("VDRUUID", destUuid); timerDb->setCharValue("TYPE", type); @@ -54,6 +54,7 @@ class cMenuDb : public cParameters friend class cMenuEpgTimers; friend class cMenuEpgSearchTimers; friend class cEpgMenuDones; + friend class cEpgMenuDonesOf; friend class cEpgMenuSearchTimerEdit; friend class cMenuEpgMatchRecordings; friend class cEpgMenuSearchResult; @@ -304,6 +305,15 @@ class cEpgMenuTextItem : public cOsdItem { cid = 0; id = aId; + row = 0; + SetText(text); + } + + cEpgMenuTextItem(cDbRow* aRow, const char* text) + { + cid = 0; + id = na; + row = aRow; SetText(text); } @@ -313,14 +323,20 @@ class cEpgMenuTextItem : public cOsdItem SetText(text); } - virtual ~cEpgMenuTextItem() { free(cid); } + virtual ~cEpgMenuTextItem() + { + free(cid); + delete row; + } - long getId() { return id; } + cDbRow* getRow() { return row; } + long getId() { return id; } const char* getCharId() { return cid; } protected: long id; + cDbRow* row; char* cid; }; @@ -18,7 +18,7 @@ //*************************************************************************** cEpgMenuDones::cEpgMenuDones() - : cOsdMenu("", 2, 20, 35) + : cOsdMenu("", 2, 20, 35, 40) { journalFilter = jfAll; order = 0; @@ -48,7 +48,6 @@ void cEpgMenuDones::setHelp() case jfCreated: btGreen = tr("Failed"); break; case jfFailed: btGreen = tr("Deleted"); break; case jfDeleted: btGreen = tr("Recorded"); break; - } SetHelp(tr("All"), btGreen, tr("Delete"), 0); @@ -69,11 +68,11 @@ int cEpgMenuDones::refresh() switch (journalFilter) { - case jfAll: state = "%"; SetTitle(tr("Timer journal")); break; - case jfRecorded: state = "R"; SetTitle(tr("Timer journal - Recorded")); break; - case jfCreated: state = "C"; SetTitle(tr("Timer journal - Created")); break; - case jfFailed: state = "F"; SetTitle(tr("Timer journal - Failed")); break; - case jfDeleted: state = "D"; SetTitle(tr("Timer journal - Delete")); break; + case jfAll: state = "%"; SetTitle(tr("Timer Journal")); break; + case jfRecorded: state = "R"; SetTitle(tr("Timer Journal - Recorded")); break; + case jfCreated: state = "C"; SetTitle(tr("Timer Journal - Created")); break; + case jfFailed: state = "F"; SetTitle(tr("Timer Journal - Failed")); break; + case jfDeleted: state = "D"; SetTitle(tr("Timer Journal - Delete")); break; } // fill menu .. diff --git a/menusched.c b/menusched.c index 9b0a466..93b032e 100644 --- a/menusched.c +++ b/menusched.c @@ -762,8 +762,6 @@ int cMenuEpgWhatsOn::LoadSearch(const cUserTimes::UserTime* userTime) #if defined (APIVERSNUM) && (APIVERSNUM >= 20301) LOCK_CHANNELS_READ; const cChannels* channels = Channels; - // cChannelsLock channelsLock(false); - // const cChannels* channels = channelsLock.Channels(); #else cChannels* channels = &Channels; #endif @@ -1050,15 +1048,7 @@ eOSState cMenuEpgWhatsOn::Record() menuDb->getParameter(menuDb->user.c_str(), "timerDefaultVDRuuid", timerDefaultVDRuuid); - // // Menü bei 'aktuellem' Event Timer Dialog öffen -> #TODO - - // if (item->event && item->event->StartTime() < time(0) + NEWTIMERLIMIT) - // { - // // timer = newTimerObjectFromRow(timerRow, xxxxx); - // // return AddSubMenu(new cMenuEpgEditTimer(menuDb, timer)); - // } - - // ansonsten direkt anlegen + // create it menuDb->createTimer(timerRow, isEmpty(timerDefaultVDRuuid) || Epg2VdrConfig.createTimerLocal ? Epg2VdrConfig.uuid : timerDefaultVDRuuid); delete timerRow; @@ -1134,12 +1124,12 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) break; } - case k3: // search timer dialog + case k3: // search timer dialog { return AddSubMenu(new cMenuEpgSearchTimers()); } - case k4: // Umschalt Timer erstellen + case k4: // Umschalt Timer erstellen { if (cMenuEpgScheduleItem* mi = (cMenuEpgScheduleItem*)Get(Current())) { @@ -1207,13 +1197,10 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) { cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); - if (item) + if (Count() && item) { - const cEvent* event = item->event; - - if (Count() && event) - return AddSubMenu(new cMenuEpgEvent(menuDb, event, schedules, - item->timerMatch, dispSchedule, canSwitch)); + if (const cEvent* event = item->event) + return AddSubMenu(new cMenuEpgEvent(menuDb, event, schedules, item->timerMatch, dispSchedule, canSwitch)); } } diff --git a/menusearchtimer.c b/menusearchtimer.c index cae3e42..ad125b3 100644 --- a/menusearchtimer.c +++ b/menusearchtimer.c @@ -9,8 +9,138 @@ #include "lib/searchtimer.h" #include "menu.h" +#include "lib/vdrlocks.h" //*************************************************************************** +// class cEpgMenuDonesOf +//*************************************************************************** + +class cEpgMenuDonesOf : public cOsdMenu +{ + public: + + cEpgMenuDonesOf(cMenuDb* mdb, const cDbRow* aRow); + virtual ~cEpgMenuDonesOf(); + virtual eOSState ProcessKey(eKeys Key); + + protected: + + int refresh(); + + // data + + const cDbRow* useEventRow; + cMenuDb* menuDb; +}; + +//*************************************************************************** +// Object +//*************************************************************************** + +cEpgMenuDonesOf::cEpgMenuDonesOf(cMenuDb* mdb, const cDbRow* aRow) + : cOsdMenu(tr("Timer Journal"), 2, 20, 35, 40) +{ + menuDb = mdb; + useEventRow = aRow; + + refresh(); +} + +cEpgMenuDonesOf::~cEpgMenuDonesOf() +{ +} + +//*************************************************************************** +// Refresh +//*************************************************************************** + +int cEpgMenuDonesOf::refresh() +{ + cDbStatement* selectDones = 0; + + Clear(); + + menuDb->useeventsDb->clear(); + menuDb->useeventsDb->getRow()->copyValues(useEventRow, cDbService::ftPrimary); + + if (!menuDb->useeventsDb->find()) + return done; + + // tell(0, "EVENT found: '%s/%s/%ld' [%s / %s]", + // menuDb->useeventsDb->getStrValue("CNTSOURCE"), + // menuDb->useeventsDb->getStrValue("CHANNELID"), + // menuDb->useeventsDb->getBigintValue("CNTEVENTID"), + // menuDb->useeventsDb->getStrValue("EPISODECOMPPARTNAME"), + // menuDb->useeventsDb->getStrValue("COMPSHORTTEXT")); + + // collect dones ... + + if (menuDb->search->prepareDoneSelect(menuDb->useeventsDb->getRow(), + menuDb->searchtimerDb->getIntValue("REPEATFIELDS"), + selectDones) == success && selectDones) + { + for (int f = selectDones->find(); f; f = selectDones->fetch()) + { + char* buf; + + menuDb->search->getTimersDoneDb()->find(); + + asprintf(&buf, "%s\t%s\t%s\t%s", + menuDb->search->getTimersDoneDb()->getStrValue("STATE"), + l2pTime(menuDb->search->getTimersDoneDb()->getIntValue("STARTTIME"), "%d.%m.%y %H:%M").c_str(), + menuDb->search->getTimersDoneDb()->getStrValue("TITLE"), + menuDb->search->getTimersDoneDb()->getStrValue("SHORTTEXT")); + + tell(0, "%s", buf); + Add(new cEpgMenuTextItem(menuDb->search->getTimersDoneDb()->getIntValue("ID"), buf)); + free(buf); + } + + selectDones->freeResult(); + } + + menuDb->useeventsDb->reset(); + + SetHelp(0, 0, tr("Delete"), 0); + Display(); + + return success; +} + +//*************************************************************************** +// ProcessKey +//*************************************************************************** + +eOSState cEpgMenuDonesOf::ProcessKey(eKeys Key) +{ + eOSState state = cOsdMenu::ProcessKey(Key); + + if (state == osUnknown) + { + switch (Key) + { + case kYellow: + { + cEpgMenuTextItem* item = (cEpgMenuTextItem*)Get(Current()); + + if (item && Interface->Confirm(tr("Delete timer from journal?"))) + { + menuDb->timerDoneDb->deleteWhere("id = %ld", item->getId()); + refresh(); + } + + return osContinue; + } + + default: break; + } + } + + return state; +} + +//*************************************************************************** +//*************************************************************************** // Class cEpgMenuSearchTimerEdit //*************************************************************************** @@ -87,7 +217,7 @@ class cEpgMenuSearchTimerItem : public cOsdItem SetText(text); } - ~cEpgMenuSearchTimerItem() { } + ~cEpgMenuSearchTimerItem() {} long getId() { return id; } int isActive() { return active; } @@ -107,22 +237,22 @@ class cEpgMenuSearchResult : public cOsdMenu { public: - cEpgMenuSearchResult(cMenuDb* db, long id); + cEpgMenuSearchResult(cMenuDb* db, long searchTimerId); virtual ~cEpgMenuSearchResult(); virtual eOSState ProcessKey(eKeys Key); protected: - int refresh(long id); + int refresh(long searchTimerId); cMenuDb* menuDb; }; -cEpgMenuSearchResult::cEpgMenuSearchResult(cMenuDb* db, long id) - : cOsdMenu(tr("Edit Search Timer"), 17, CHNAMWIDTH, 3, 30) +cEpgMenuSearchResult::cEpgMenuSearchResult(cMenuDb* db, long searchTimerId) + : cOsdMenu(tr("Search Result"), 17, CHNAMWIDTH, 3, 30) { menuDb = db; - refresh(id); + refresh(searchTimerId); } cEpgMenuSearchResult::~cEpgMenuSearchResult() @@ -133,11 +263,11 @@ cEpgMenuSearchResult::~cEpgMenuSearchResult() // Refresh //*************************************************************************** -int cEpgMenuSearchResult::refresh(long id) +int cEpgMenuSearchResult::refresh(long searchTimerId) { cDbStatement* select = 0; - menuDb->searchtimerDb->setValue("ID", id); + menuDb->searchtimerDb->setValue("ID", searchTimerId); if (!menuDb->searchtimerDb->find()) return done; @@ -145,14 +275,7 @@ int cEpgMenuSearchResult::refresh(long id) if (!(select = menuDb->search->prepareSearchStatement(menuDb->searchtimerDb->getRow(), menuDb->useeventsDb))) return fail; -#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) - LOCK_CHANNELS_READ; - const cChannels* channels = Channels; - // cChannelsLock channelsLock(false); - // const cChannels* channels = channelsLock.Channels(); -#else - cChannels* channels = &Channels; -#endif + GET_CHANNELS_READ(channels); menuDb->useeventsDb->clear(); @@ -170,11 +293,8 @@ int cEpgMenuSearchResult::refresh(long id) if (menuDb->search->prepareDoneSelect(menuDb->useeventsDb->getRow(), menuDb->searchtimerDb->getIntValue("REPEATFIELDS"), - selectDones) == success - && selectDones) + selectDones) == success && selectDones) { - // first only count - #TODO show them in a sub-menu oder let delete by kYellow? - for (int f = selectDones->find(); f; f = selectDones->fetch()) cnt++; @@ -183,22 +303,25 @@ int cEpgMenuSearchResult::refresh(long id) // + cDbRow* useEventRow = new cDbRow("useevents"); + useEventRow->copyValues(menuDb->useeventsDb->getRow(), cDbService::ftPrimary); + const char* strChannelId = menuDb->useeventsDb->getStrValue("CHANNELID"); const cChannel* channel = channels->GetByChannelID(tChannelID::FromString(strChannelId)); - Add(new cEpgMenuTextItem(menuDb->useeventsDb->getIntValue("USEID"), + Add(new cEpgMenuTextItem(useEventRow, cString::sprintf("%s\t%s\t%s\t%s\t%s", l2pTime(menuDb->useeventsDb->getIntValue("STARTTIME")).c_str(), channel->Name(), cnt ? num2Str(cnt).c_str() : "", menuDb->useeventsDb->getStrValue("TITLE"), menuDb->useeventsDb->getStrValue("SHORTTEXT")))); - } + } select->freeResult(); menuDb->searchtimerDb->reset(); - SetHelp(0, 0, "Delete dones", 0); + SetHelp(0, tr("Show Journal"), 0, 0); Display(); return success; @@ -216,30 +339,10 @@ eOSState cEpgMenuSearchResult::ProcessKey(eKeys Key) { switch (Key) { - case kYellow: + case kGreen: { - cDbStatement* selectDones = 0; cEpgMenuTextItem* item = (cEpgMenuTextItem*)Get(Current()); - - if (item && Interface->Confirm(tr("Remove all done entries of this event?"))) - { - menuDb->useeventsDb->clear(); - menuDb->useeventsDb->setValue("USEID", item->getId()); - - if (menuDb->useeventsDb->find()) - { - if (menuDb->search->prepareDoneSelect(menuDb->useeventsDb->getRow(), - menuDb->searchtimerDb->getIntValue("REPEATFIELDS"), - selectDones) == success - && selectDones) - { - for (int f = selectDones->find(); f; f = selectDones->fetch()) - selectDones->getTable()->deleteWhere("id = %ld", selectDones->getTable()->getIntValue("ID")); - - selectDones->freeResult(); - } - } - } + return AddSubMenu(new cEpgMenuDonesOf(menuDb, item->getRow())); } default: break; @@ -305,7 +408,7 @@ void cMenuEpgSearchTimers::setHelpKeys() if (item) SetHelp(item->isActive() ? tr("Deactivate") : tr("Activate"), - tr("Test"), + tr("Check"), tr("Delete"), 0); else @@ -327,7 +430,7 @@ eOSState cMenuEpgSearchTimers::ProcessKey(eKeys Key) { switch (Key) { - case kOk: + case kOk: // edit search timer { if (HasSubMenu() || Count() == 0) return osContinue; @@ -336,7 +439,7 @@ eOSState cMenuEpgSearchTimers::ProcessKey(eKeys Key) return AddSubMenu(new cEpgMenuSearchTimerEdit(menuDb, item->getId())); } - case kRed: + case kRed: // ativate/deactivate search timer { menuDb->searchtimerDb->setValue("ID", item->getId()); @@ -350,12 +453,12 @@ eOSState cMenuEpgSearchTimers::ProcessKey(eKeys Key) return osContinue; } - case kGreen: + case kGreen: // test search { return AddSubMenu(new cEpgMenuSearchResult(menuDb, item->getId())); } - case kYellow: + case kYellow: // delete search timer { if (item && Interface->Confirm(tr("Delete search timer?"))) { diff --git a/parameters.c b/parameters.c index fdd3e4b..3598f41 100644 --- a/parameters.c +++ b/parameters.c @@ -59,7 +59,9 @@ cParameters::Parameter cParameters::parameters[] = { "@", "defaultVDRuuid", ptAscii, "", "^.{0,150}$", no, yes }, { "@", "startPage", ptAscii, "menu_magazine", "^.{0,150}$", no, yes }, { "@", "timerDefaultVDRuuid", ptAscii, "", "^.{0,150}$", no, yes }, - { "@", "quickTimes", ptAscii, "Now=@Now~Next=@Next~PrimeTime=20:15~LateNight=00:00", "^(~?[^=]+=(([0-1]?[0-9]|2[0-4]):[0-5]?[0-9]|@Now|@Next))*$", no, yes }, + { "@", "quickTimes", ptAscii, "Jetzt=@Now~Nächste=@Next~PrimeTime=20:20~EarlyNight=!22:20~MidNight=!00:00~LateNight=!02:00~Tipp=@TagesTipps~Action=@Action", + "^(~?[^=]+=!?(([0-1]?[0-9]|2[0-4]):[0-5]?[0-9]|@Now|@Next|@[A-Za-z0-9]*))*$", + no, yes }, { "@", "startWithSched", ptBool, "0", "^[01]$", no, yes }, { "@", "searchAdv", ptBool, "1", "^[01]$", no, yes }, { "@", "namingModeSerie", ptNum, "1", "^[0-5]$", no, yes }, @@ -70,6 +72,7 @@ cParameters::Parameter cParameters::parameters[] = { "@", "sendTCC", ptBool, "1", "^[01]$", no, yes }, { "@", "constabelLoginPath", ptAscii, "", "^.{0,150}$", no, yes }, { "@", "mailReceiver", ptAscii, "", "^.{0,150}$", no, yes }, + { "@", "osdTimerNotify", ptBool, "0", "^[01]$", no, yes }, { 0, 0, 0, 0, 0, 0, 0 } }; diff --git a/po/de_DE.po b/po/de_DE.po index 92e8c60..d1c0a6f 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: <vdr@jwendel.de>\n" -"POT-Creation-Date: 2018-03-07 17:36+0100\n" +"POT-Creation-Date: 2018-03-09 08:55+0100\n" "PO-Revision-Date: 2009-08-27 21:40+0200\n" "Last-Translator: Klaus Schmidinger <kls@cadsoft.de>\n" "Language-Team: <vdr@linuxtv.org>\n" @@ -22,7 +22,7 @@ msgstr "" msgid "Search Timer" msgstr "Suchtimer" -msgid "Timer journal" +msgid "Timer Journal" msgstr "Timerhistorie" msgid "Program" @@ -71,7 +71,7 @@ msgid "Blacklist not configured Channels" msgstr "Nicht konfigurierte Kanäle 'blacklisten'" msgid "Store extended EPD Data to AUX (e.g. for Skins)" -msgstr "" +msgstr "Erweitertes EPG in AUX speichern (für Skins)" msgid "Menu" msgstr "Menü" @@ -157,32 +157,32 @@ msgstr "Alle" msgid "Delete" msgstr "Löschen" -msgid "Timer journal - Recorded" +msgid "Timer Journal - Recorded" msgstr "Timerhistorie - Aufgenommen" -msgid "Timer journal - Created" +msgid "Timer Journal - Created" msgstr "Timerhistorie - Erzeugt" -msgid "Timer journal - Failed" +msgid "Timer Journal - Failed" msgstr "Timerhistorie - Fehlgeschlagen" -msgid "Timer journal - Delete" +msgid "Timer Journal - Delete" msgstr "Timerhistorie - Gelöscht" msgid "Delete timer from journal?" msgstr "Eintrag aus Timerhistorie löschen?" msgid "Search matching Events" -msgstr "" +msgstr "Wiederholungen" msgid "Search matching Recordings" -msgstr "" +msgstr "Vorhandene Aufnahmen" msgid "Searchtimers" -msgstr "" +msgstr "Suchtimer" msgid "Switch Timer" -msgstr "" +msgstr "Umschalttimer" msgid "Matching recordings" msgstr "Vorhandene Aufnahmen" @@ -194,7 +194,7 @@ msgid "Similar Matches:" msgstr "Ähnliche Aufnahmen:" msgid "Event" -msgstr "" +msgstr "Sendung" msgid "Button$Timer" msgstr "Timer" @@ -232,8 +232,11 @@ msgstr "Umschalten nicht möglich!" msgid "Edit Search Timer" msgstr "Suchtimer bearbeiten" -msgid "Remove all done entries of this event?" -msgstr "Alle erledigten Einträge dieses Ereignisses entfernen?" +msgid "Search Result" +msgstr "Suchergebnis" + +msgid "Show Journal" +msgstr "Timerhistorie" msgid "Search Timers" msgstr "Suchtimer" @@ -244,8 +247,8 @@ msgstr "Deaktivieren" msgid "Activate" msgstr "Aktivieren" -msgid "Test" -msgstr "" +msgid "Check" +msgstr "Test" msgid "Delete search timer?" msgstr "Suchtimer löschen?" @@ -257,7 +260,7 @@ msgid "Active" msgstr "Aktiv" msgid "Type" -msgstr "" +msgstr "Typ" msgid "VDR" msgstr "" @@ -333,11 +336,11 @@ msgstr "Timer zeichnet auf, dennoch löschen?" #, c-format msgid "Switching in %ld seconds to '%s'" -msgstr "" +msgstr "In %ld sekunden umschalten zu '%s'" #, c-format msgid "Skipping '%s' request, epgd busy. Trying again later" -msgstr "" +msgstr "epgd beschäftigt, '%s' request wird später ausgeführt" msgid "reload" msgstr "neu laden" @@ -348,24 +351,3 @@ msgstr "aktualisieren" #, c-format msgid "EPG '%s' done" msgstr "EPG '%s' abgeschlossen" - -#~ msgid "Now" -#~ msgstr "Jetzt" - -#~ msgid "Next" -#~ msgstr "Nächste" - -#~ msgid "This event - %s" -#~ msgstr "Dieses Ereignis - %s" - -#~ msgid "This event - all channels" -#~ msgstr "Dieses Ereignis - alle Kanäle" - -#~ msgid "All events - all channels" -#~ msgstr "Alle Ereignisse - alle Kanäle" - -#~ msgid "Button$Now" -#~ msgstr "Jetzt" - -#~ msgid "Button$Next" -#~ msgstr "Nächste" diff --git a/po/it_IT.po b/po/it_IT.po index c8afd18..a3bf897 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: <vdr@jwendel.de>\n" -"POT-Creation-Date: 2018-03-07 17:36+0100\n" +"POT-Creation-Date: 2018-03-09 09:00+0100\n" "PO-Revision-Date: 2009-08-27 21:45+0100\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Language-Team: <vdr@linuxtv.org>\n" @@ -27,7 +27,7 @@ msgstr "" msgid "Search Timer" msgstr "" -msgid "Timer journal" +msgid "Timer Journal" msgstr "" msgid "Program" @@ -162,16 +162,16 @@ msgstr "" msgid "Delete" msgstr "" -msgid "Timer journal - Recorded" +msgid "Timer Journal - Recorded" msgstr "" -msgid "Timer journal - Created" +msgid "Timer Journal - Created" msgstr "" -msgid "Timer journal - Failed" +msgid "Timer Journal - Failed" msgstr "" -msgid "Timer journal - Delete" +msgid "Timer Journal - Delete" msgstr "" msgid "Delete timer from journal?" @@ -237,7 +237,10 @@ msgstr "" msgid "Edit Search Timer" msgstr "" -msgid "Remove all done entries of this event?" +msgid "Search Result" +msgstr "" + +msgid "Show Journal" msgstr "" msgid "Search Timers" @@ -249,7 +252,7 @@ msgstr "" msgid "Activate" msgstr "" -msgid "Test" +msgid "Check" msgstr "" msgid "Delete search timer?" @@ -229,10 +229,10 @@ int cUpdate::performRecordingActions() complete = recFraction >= (vpsUsed ? 90 : 98); if (complete) - tell(1, "Info: Finished: '%s'; recorded %d%%; VPS %s", + tell(1, "Info: Finished (%d) '%s'; recorded %d%%; VPS %s", getTimerIdOf(rr->aux), rr->timer->File(), (int)round(recFraction), vpsUsed ? "Yes": "No"); else - tell(1, "Info: Finished: '%s' (not complete! - recorded only %d%%); VPS %s", + tell(1, "Info: Finished (%d) '%s' (not complete! - recorded only %d%%); VPS %s", getTimerIdOf(rr->aux), rr->timer->File(), (int)round(recFraction), vpsUsed ? "Yes": "No"); if (complete) @@ -60,7 +60,7 @@ int cUpdate::checkSwitchTimer() tell(0, "Switching to channel '%s'", channel->Name()); if (!cDevice::PrimaryDevice()->SwitchChannel(channel, true)) - Skins.Message(mtError, tr("Can't switch channel!")); + Skins.QueueMessage(mtError, tr("Can't switch channel!")); else res = success; } @@ -175,6 +175,19 @@ int cUpdate::performTimerJobs() return fail; } + // move this to cUpdate::init() + + std::string user = "@"; + long int webLoginEnabled = no; + long int osdTimerNotify = no; + + getParameter("webif", "needLogin", webLoginEnabled); + + if (webLoginEnabled) + user += Epg2VdrConfig.user; + + getParameter(user.c_str(), "osdTimerNotify", osdTimerNotify); + // iterate pending actions ... timerDb->clear(); @@ -239,6 +252,9 @@ int cUpdate::performTimerJobs() timerDb->setCharValue("ACTION", taAssumed); timerDb->setCharValue("STATE", tsDeleted); timerDb->update(); + + if (osdTimerNotify) + Skins.QueueMessage(mtInfo, cString::sprintf("Timer '%s' deleted", timerDb->getStrValue("FILE"))); } // -------------------------------- @@ -427,6 +443,9 @@ int cUpdate::performTimerJobs() timerDb->setCharValue("ACTION", taAssumed); timerDb->setCharValue("STATE", tsPending); timerDb->store(); + + if (osdTimerNotify) + Skins.QueueMessage(mtInfo, cString::sprintf("Timer '%s' %s", timerDb->getStrValue("FILE"), insert ? "created" : "modified")); } } @@ -654,7 +673,9 @@ int cUpdate::updateTimerTable() { int doneid = timerDb->getIntValue("DONEID"); - if (!timerDb->hasCharValue("STATE", tsFinished)) + if (!timerDb->hasCharValue("STATE", tsFinished) && + !timerDb->hasCharValue("STATE", tsRunning) && + !timerDb->hasCharValue("STATE", tsError)) { timerDb->setCharValue("STATE", tsDeleted); timerDb->update(); |