summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2014-12-30 19:52:21 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2015-06-13 17:29:37 +0100
commitf31ff1177eec7ffa0ea6375b77d78d69559f9c88 (patch)
tree9e3bbb6dabbf2b082d793ca470fb8c790225663d
parentDon't create comically broken sample data and fix the last sample (diff)
downloadp2pvr-f31ff1177eec7ffa0ea6375b77d78d69559f9c88.tar.bz2
p2pvr-f31ff1177eec7ffa0ea6375b77d78d69559f9c88.tar.xz
p2pvr-f31ff1177eec7ffa0ea6375b77d78d69559f9c88.zip
Big commit comprising mostly of changes to the DB structure to unify recorded event details into events, lots of new unit tests
-rw-r--r--p2pvr/daemon/Jamfile.jam2
-rw-r--r--p2pvr/daemon/events.cpp101
-rw-r--r--p2pvr/daemon/maintenance/events.cpp6
-rw-r--r--p2pvr/daemon/recorder.cpp11
-rw-r--r--p2pvr/daemon/recorder.h4
-rw-r--r--p2pvr/daemon/recordings.cpp21
-rw-r--r--p2pvr/daemon/schedules.cpp61
-rw-r--r--p2pvr/daemon/schedules.h5
-rw-r--r--p2pvr/daemon/si.cpp49
-rw-r--r--p2pvr/daemon/si.h13
-rw-r--r--p2pvr/daemon/sql/Maint_pruneEvents.sql4
-rw-r--r--p2pvr/daemon/sql/Recordings_getAll.sql4
-rw-r--r--p2pvr/daemon/sql/Recordings_insert.sql4
-rw-r--r--p2pvr/daemon/sql/SI_eventById.sql10
-rw-r--r--p2pvr/daemon/sql/SI_eventByUid.sql30
-rw-r--r--p2pvr/daemon/sql/SI_eventSearch.sql5
-rw-r--r--p2pvr/daemon/sql/SI_eventsInRange.sql8
-rw-r--r--p2pvr/daemon/sql/SI_eventsInSchedule.sql11
-rw-r--r--p2pvr/daemon/sql/SI_eventsInSchedules.sql11
-rw-r--r--p2pvr/daemon/sql/SI_eventsOnNow.sql8
-rw-r--r--p2pvr/daemon/sql/SI_serviceNextUsed.sql9
-rw-r--r--p2pvr/daemon/sql/Schedules_GetCandidates.sql19
-rw-r--r--p2pvr/daemon/sql/Schedules_insert.sql2
-rw-r--r--p2pvr/daemon/sql/Schedules_scheduledToRecord.sql5
-rw-r--r--p2pvr/daemon/sql/Schedules_selectAll.sql2
-rw-r--r--p2pvr/daemon/sql/Schedules_selectById.sql3
-rw-r--r--p2pvr/daemon/sql/Schedules_update.sql2
-rw-r--r--p2pvr/daemon/unittests/Jamfile.jam60
-rw-r--r--p2pvr/daemon/unittests/mockDevices.cpp29
-rw-r--r--p2pvr/daemon/unittests/mockDevices.h16
-rw-r--r--p2pvr/daemon/unittests/mockRecorder.cpp8
-rw-r--r--p2pvr/daemon/unittests/mockRecorder.h12
-rw-r--r--p2pvr/daemon/unittests/mockScheduler.cpp36
-rw-r--r--p2pvr/daemon/unittests/mockScheduler.h17
-rw-r--r--p2pvr/daemon/unittests/testMaint.cpp128
-rw-r--r--p2pvr/daemon/unittests/testRecordings.cpp74
-rw-r--r--p2pvr/daemon/unittests/testSched.cpp102
-rw-r--r--p2pvr/daemon/unittests/testSi.cpp105
-rw-r--r--p2pvr/daemon/unittests/testp2ice.cpp37
-rw-r--r--p2pvr/datasources/schema.sql104
-rw-r--r--p2pvr/devices/mockTuner.cpp10
-rw-r--r--p2pvr/devices/mockTuner.h5
-rw-r--r--p2pvr/ice/common.ice4
-rw-r--r--p2pvr/ice/commonHelpers.cpp2
-rw-r--r--p2pvr/ice/commonHelpers.h12
-rw-r--r--p2pvr/ice/p2pvr.ice40
-rw-r--r--p2pvr/lib/containerCreator.h3
-rw-r--r--p2pvr/lib/dvbsiHelpers/event.cpp48
-rw-r--r--p2pvr/lib/p2pvrHelpers/schedule.cpp6
49 files changed, 968 insertions, 300 deletions
diff --git a/p2pvr/daemon/Jamfile.jam b/p2pvr/daemon/Jamfile.jam
index ac3ed58..d9894d3 100644
--- a/p2pvr/daemon/Jamfile.jam
+++ b/p2pvr/daemon/Jamfile.jam
@@ -11,7 +11,7 @@ cpp-pch pch : pch.hpp :
lib p2pvrdaemon :
pch
- [ glob-tree *.cpp *.sql : dummy* test*.cpp ]
+ [ glob-tree *.cpp *.sql : dummy* test*.cpp mock*.cpp ]
:
<library>../ice//p2pvrice
<library>../lib//p2pvrlib
diff --git a/p2pvr/daemon/events.cpp b/p2pvr/daemon/events.cpp
new file mode 100644
index 0000000..676b2b3
--- /dev/null
+++ b/p2pvr/daemon/events.cpp
@@ -0,0 +1,101 @@
+#include <pch.hpp>
+#include "containerCreator.h"
+#include <p2pvr.h>
+#include <p2Helpers.h>
+
+template<>
+void
+CreateColumns<P2PVR::EventPtr>(const ColumnCreator & cc)
+{
+ cc("eventUid", false);
+ cc("serviceId", true);
+ cc("eventId", true);
+ cc("title", false);
+ cc("titleLang", false);
+ cc("subtitle", false);
+ cc("description", false);
+ cc("descriptionLang", false);
+ cc("videoAspect", false);
+ cc("videoFrameRate", false);
+ cc("videoHd", false);
+ cc("audioChannels", false);
+ cc("audioLanguage", false);
+ cc("subtitleLanguage", false);
+ cc("category", false);
+ cc("subCategory", false);
+ cc("userCategory", false);
+ cc("dvbRating", false);
+ cc("startTime", false);
+ cc("stopTime", false);
+ cc("episode", false);
+ cc("episodes", false);
+ cc("year", false);
+ cc("flags", false);
+ cc("season", false);
+ cc("current", false);
+}
+
+template<>
+void
+BindColumns(RowState & rs, const P2PVR::EventPtr & e)
+{
+ rs.fields[0] << e->ServiceId;
+ rs.fields[1] << e->EventId;
+ rs.fields[2] << e->Title;
+ rs.fields[3] << e->TitleLang;
+ rs.fields[4] << e->Subtitle;
+ rs.fields[5] << e->Description;
+ rs.fields[6] << e->DescriptionLang;
+ rs.fields[7] << e->VideoAspect;
+ rs.fields[8] << e->VideoFrameRate;
+ rs.fields[9] << e->VideoHD;
+ rs.fields[10] << e->AudioChannels;
+ rs.fields[11] << e->AudioLanguage;
+ rs.fields[12] << e->SubtitleLanguage;
+ rs.fields[13] << e->Category;
+ rs.fields[14] << e->SubCategory;
+ rs.fields[15] << e->UserCategory;
+ rs.fields[16] << e->DvbRating;
+ rs.fields[17] << e->StartTime;
+ rs.fields[18] << e->StopTime;
+ rs.fields[19] << e->Episode;
+ rs.fields[20] << e->Episodes;
+ rs.fields[21] << e->Year;
+ rs.fields[22] << e->Flags;
+ rs.fields[23] << e->Season;
+ rs.fields[24] << e->EventUid;
+ rs.fields[25] << e->Current;
+}
+
+template<>
+void
+UnbindColumns(RowState & rs, const P2PVR::EventPtr & e)
+{
+ rs.fields[0] >> e->ServiceId;
+ rs.fields[1] >> e->EventId;
+ rs.fields[2] >> e->Title;
+ rs.fields[3] >> e->TitleLang;
+ rs.fields[4] >> e->Subtitle;
+ rs.fields[5] >> e->Description;
+ rs.fields[6] >> e->DescriptionLang;
+ rs.fields[7] >> e->VideoAspect;
+ rs.fields[8] >> e->VideoFrameRate;
+ rs.fields[9] >> e->VideoHD;
+ rs.fields[10] >> e->AudioChannels;
+ rs.fields[11] >> e->AudioLanguage;
+ rs.fields[12] >> e->SubtitleLanguage;
+ rs.fields[13] >> e->Category;
+ rs.fields[14] >> e->SubCategory;
+ rs.fields[15] >> e->UserCategory;
+ rs.fields[16] >> e->DvbRating;
+ rs.fields[17] >> e->StartTime;
+ rs.fields[18] >> e->StopTime;
+ rs.fields[19] >> e->Episode;
+ rs.fields[20] >> e->Episodes;
+ rs.fields[21] >> e->Year;
+ rs.fields[22] >> e->Flags;
+ rs.fields[23] >> e->Season;
+ rs.fields[24] >> e->EventUid;
+ rs.fields[25] >> e->Current;
+}
+
diff --git a/p2pvr/daemon/maintenance/events.cpp b/p2pvr/daemon/maintenance/events.cpp
index 648be0b..f075a32 100644
--- a/p2pvr/daemon/maintenance/events.cpp
+++ b/p2pvr/daemon/maintenance/events.cpp
@@ -9,6 +9,9 @@
#include <singleIterator.h>
#include <temporaryIceAdapterObject.h>
#include <commonHelpers.h>
+#include <resources.h>
+
+ResourceString(Maint_pruneEvents, sql_Maint_pruneEvents);
class SiEventsHandler : public SiEpgParser {
public:
@@ -81,8 +84,11 @@ Maintenance::UpdateEvents(short type, const Ice::Current & ice)
SqlMergeTask mergeEvents("postgres", "events");
CreateColumns<DVBSI::EventPtr>(boost::bind(SqlMergeColumnsInserter, &mergeEvents, _1, _2));
mergeEvents.sources.insert(new SiEventsMerger(type, ice));
+ mergeEvents.insteadOfDelete = new DynamicSql::SqlText("SET current = false");
+ mergeEvents.updateWhere = new DynamicSql::SqlText("a.current");
mergeEvents.loadComplete(this);
mergeEvents.execute(NULL);
+ Modify(Maint_pruneEvents).second->execute();
tx.Commit();
Logger()->messagebf(LOG_INFO, "%s: Updated events", __PRETTY_FUNCTION__);
diff --git a/p2pvr/daemon/recorder.cpp b/p2pvr/daemon/recorder.cpp
index 6cd0b5f..35aeba8 100644
--- a/p2pvr/daemon/recorder.cpp
+++ b/p2pvr/daemon/recorder.cpp
@@ -39,13 +39,13 @@ Recorder::RefreshSchedules(const Ice::Current &)
auto si = P2PVR::SIPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("SI")));
BOOST_FOREACH(const auto & s, schedules->GetScheduledToRecord()) {
if (std::find_if(currentRecordings.begin(), currentRecordings.end(), [&s](const CurrentPtr & c) {
- return s->ScheduleId == c->schedule->ScheduleId && s->ServiceId == c->event->ServiceId && s->EventId == c->event->EventId;;
+ return s->ScheduleId == c->schedule->ScheduleId && s->EventUid == c->event->EventUid;
}) != currentRecordings.end()) {
continue;
}
auto schedule = schedules->GetSchedule(s->ScheduleId);
- auto service = si->GetService(s->ServiceId);
- auto event = si->GetEvent(s->ServiceId, s->EventId);
+ auto event = si->GetEvents({ s->EventUid }).front();
+ auto service = si->GetService(event->ServiceId);
auto startIn = std::max<time_t>((*event->StartTime - *schedule->Early - boost::posix_time::second_clock::universal_time()).total_seconds(), 0);
IceUtil::TimerTaskPtr startTimer = new BindTimerTask(boost::bind(&Recorder::StartRecording, this, schedule, service, event));
@@ -56,7 +56,7 @@ Recorder::RefreshSchedules(const Ice::Current &)
}
void
-Recorder::StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service, DVBSI::EventPtr event)
+Recorder::StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service, P2PVR::EventPtr event)
{
std::lock_guard<std::mutex> g(lock);
auto storage = P2PVR::StoragePrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Storage")));
@@ -79,8 +79,7 @@ Recorder::StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service,
event->Title, event->StartTime, event->StopTime,
service->Name ? *service->Name : "<no name>", service->ServiceId);
- recordings->NewRecording(new P2PVR::Recording(0, storage->ice_toString(), id, schedule->ScheduleId, event->Title, event->Subtitle,
- event->Description, event->StartTime, *(*event->StopTime - *event->StartTime)));
+ recordings->NewRecording(new P2PVR::Recording(0, storage->ice_toString(), id, schedule->ScheduleId, event->EventUid));
auto newCurrent = CurrentPtr(new Current({muxer, store, ss, schedule, service, event, IceUtil::TimerTaskPtr()}));
currentRecordings.insert(newCurrent);
diff --git a/p2pvr/daemon/recorder.h b/p2pvr/daemon/recorder.h
index 78c604b..6680801 100644
--- a/p2pvr/daemon/recorder.h
+++ b/p2pvr/daemon/recorder.h
@@ -19,7 +19,7 @@ class Recorder : public P2PVR::Recorder {
ServiceStreamerPtr stream;
P2PVR::SchedulePtr schedule;
DVBSI::ServicePtr service;
- DVBSI::EventPtr event;
+ P2PVR::EventPtr event;
IceUtil::TimerTaskPtr stopTimer;
};
typedef boost::shared_ptr<Current> CurrentPtr;
@@ -33,7 +33,7 @@ class Recorder : public P2PVR::Recorder {
private:
void StartRecordings();
- void StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service, DVBSI::EventPtr event);
+ void StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service, P2PVR::EventPtr event);
void StopRecording(CurrentPtr);
Ice::ObjectAdapterPtr adapter;
diff --git a/p2pvr/daemon/recordings.cpp b/p2pvr/daemon/recordings.cpp
index 73cf77d..ceb89ba 100644
--- a/p2pvr/daemon/recordings.cpp
+++ b/p2pvr/daemon/recordings.cpp
@@ -19,11 +19,7 @@ CreateColumns<P2PVR::RecordingPtr>(const ColumnCreator & cc)
cc("storageaddress", false);
cc("guid", false);
cc("scheduleid", false);
- cc("title", false);
- cc("subtitle", false);
- cc("description", false);
- cc("starttime", false);
- cc("duration", false);
+ cc("eventuid", false);
}
template<>
@@ -34,11 +30,7 @@ UnbindColumns(RowState & rs, const P2PVR::RecordingPtr & r)
rs.fields[1] >> r->StorageAddress;
rs.fields[2] >> r->Guid;
rs.fields[3] >> r->ScheduleId;
- rs.fields[4] >> r->Title;
- rs.fields[5] >> r->Subtitle;
- rs.fields[6] >> r->Description;
- rs.fields[7] >> r->StartTime;
- rs.fields[8] >> r->Duration;
+ rs.fields[4] >> r->EventUid;
}
int
@@ -46,8 +38,7 @@ Recordings::NewRecording(const P2PVR::RecordingPtr & r, const Ice::Current &)
{
Logger()->messagebf(LOG_INFO, "%s: Creating new recording %s at %s", __PRETTY_FUNCTION__, r->Guid, r->StorageAddress);
TxHelper tx(this);
- auto insert = Modify(Recording_Insert,
- r->StorageAddress, r->Guid, r->ScheduleId, r->Title, r->Subtitle, r->Description, r->StartTime, r->Duration);
+ auto insert = Modify(Recording_Insert, r->StorageAddress, r->Guid, r->ScheduleId, r->EventUid);
insert.second->execute();
r->RecordingId = SelectScalar<int>(Recording_InsertNewId);
Logger()->messagebf(LOG_INFO, "%s: Created recording Id: %d", __PRETTY_FUNCTION__, r->RecordingId);
@@ -65,8 +56,10 @@ Recordings::DeleteRecording(int id, const Ice::Current & ice)
std::string addr = recordingStorages.second / "storageaddress";
std::string guid = recordingStorages.second / "guid";
auto storage = P2PVR::StoragePrx::checkedCast(ic->stringToProxy(addr));
- storage->Delete(guid);
- Logger()->messagebf(LOG_DEBUG, "%s: Delete %s from StorageAddress %s", __PRETTY_FUNCTION__, guid, addr);
+ if (storage) {
+ storage->Delete(guid);
+ Logger()->messagebf(LOG_DEBUG, "%s: Delete %s from StorageAddress %s", __PRETTY_FUNCTION__, guid, addr);
+ }
}
Modify(Recording_Delete, id).second->execute();
}
diff --git a/p2pvr/daemon/schedules.cpp b/p2pvr/daemon/schedules.cpp
index dab3917..b97924d 100644
--- a/p2pvr/daemon/schedules.cpp
+++ b/p2pvr/daemon/schedules.cpp
@@ -31,8 +31,7 @@ END_OPTIONS()
class ScheduleCandidate {
public:
std::string What;
- int ServiceId;
- int EventId;
+ int EventUid;
int TransportStreamId;
datetime StartTime;
datetime StopTime;
@@ -51,16 +50,14 @@ enum RecordStatuses {
class Record {
public:
Record() { };
- Record(int s, int e, RecordStatuses rs, int sc) :
- ServiceId(s),
- EventId(e),
+ Record(int e, RecordStatuses rs, int sc) :
+ EventUid(e),
RecordStatus(rs),
ScheduleId(sc)
{
}
- int ServiceId;
- int EventId;
+ int EventUid;
RecordStatuses RecordStatus;
int ScheduleId;
};
@@ -71,8 +68,7 @@ template<>
void
CreateColumns<P2PVR::ScheduledToRecordPtr>(const ColumnCreator & cc)
{
- cc("serviceid", true);
- cc("eventid", true);
+ cc("eventuid", true);
cc("scheduleid", true);
}
@@ -80,9 +76,8 @@ template<>
void
UnbindColumns(RowState & rs, P2PVR::ScheduledToRecordPtr const & s)
{
- rs.fields[0] >> s->ServiceId;
- rs.fields[1] >> s->EventId;
- rs.fields[2] >> s->ScheduleId;
+ rs.fields[0] >> s->EventUid;
+ rs.fields[1] >> s->ScheduleId;
}
template<>
@@ -91,7 +86,7 @@ CreateColumns<ScheduleCandidatePtr>(const ColumnCreator & cc)
{
cc("what", true);
cc("serviceid", false);
- cc("eventid", false);
+ cc("eventuid", false);
cc("transportstreamid", false);
cc("starttime", false);
cc("stoptime", false);
@@ -104,13 +99,12 @@ void
UnbindColumns(RowState & rs, ScheduleCandidatePtr const & s)
{
rs.fields[0] >> s->What;
- rs.fields[1] >> s->ServiceId;
- rs.fields[2] >> s->EventId;
- rs.fields[3] >> s->TransportStreamId;
- rs.fields[4] >> s->StartTime;
- rs.fields[5] >> s->StopTime;
- rs.fields[6] >> s->Priority;
- rs.fields[7] >> s->ScheduleId;
+ rs.fields[1] >> s->EventUid;
+ rs.fields[2] >> s->TransportStreamId;
+ rs.fields[3] >> s->StartTime;
+ rs.fields[4] >> s->StopTime;
+ rs.fields[5] >> s->Priority;
+ rs.fields[6] >> s->ScheduleId;
}
template<>
@@ -119,7 +113,7 @@ CreateColumns<P2PVR::SchedulePtr>(const ColumnCreator & cc)
{
cc("scheduleid", true);
cc("serviceid", false);
- cc("eventid", false);
+ cc("eventuid", false);
cc("title", false);
cc("search", false);
cc("priority", false);
@@ -134,7 +128,7 @@ UnbindColumns(RowState & rs, P2PVR::SchedulePtr const & s)
{
rs.fields[0] >> s->ScheduleId;
rs.fields[1] >> s->ServiceId;
- rs.fields[2] >> s->EventId;
+ rs.fields[2] >> s->EventUid;
rs.fields[3] >> s->Title;
rs.fields[4] >> s->Search;
rs.fields[5] >> s->Priority;
@@ -147,8 +141,7 @@ template<>
void
CreateColumns<RecordPtr>(const ColumnCreator & cc)
{
- cc("serviceid", true);
- cc("eventid", true);
+ cc("eventuid", true);
cc("recordstatus", false);
cc("scheduleid", false);
}
@@ -157,16 +150,14 @@ template<>
void
BindColumns(RowState & rs, RecordPtr const & s)
{
- rs.fields[0] << s->ServiceId;
- rs.fields[1] << s->EventId;
- rs.fields[2] << (int)s->RecordStatus;
- rs.fields[3] << s->ScheduleId;
+ rs.fields[0] << s->EventUid;
+ rs.fields[1] << (int)s->RecordStatus;
+ rs.fields[2] << s->ScheduleId;
}
-Showing::Showing(unsigned int s, unsigned int e, unsigned int t, unsigned int sc, datetime start, datetime stop, int p, const Episode * ep) :
+Showing::Showing(unsigned int e, unsigned int t, unsigned int sc, datetime start, datetime stop, int p, const Episode * ep) :
episode(ep),
- serviceId(s),
- eventId(e),
+ eventUid(e),
priority(p),
scheduleId(sc),
transportStreamId(t),
@@ -338,7 +329,7 @@ Schedules::DoReschedule(const Ice::Current & ice)
cur = new Episode(c->What);
scheduleList.push_back(cur);
}
- ShowingPtr s = new Showing(c->ServiceId, c->EventId, c->TransportStreamId, c->ScheduleId,
+ ShowingPtr s = new Showing(c->EventUid, c->TransportStreamId, c->ScheduleId,
c->StartTime, c->StopTime, c->Priority, cur.get());
minPriority = std::min(minPriority, s->priority);
cur->showings.push_back(s);
@@ -408,7 +399,7 @@ Schedules::DoReschedule(const Ice::Current & ice)
}
BOOST_FOREACH(const auto & i, c->showings) {
if (i) {
- records.push_back(RecordPtr(new Record(i->serviceId, i->eventId,
+ records.push_back(RecordPtr(new Record(i->eventUid,
found ?
selected.find(i) != selected.end() ? Record_WillRecordThisShowing : Record_WillRecordOtherShowing :
Record_CannotRecordAnyShowing, i->scheduleId)));
@@ -470,11 +461,11 @@ Schedules::UpdateSchedule(const P2PVR::SchedulePtr & s, const Ice::Current & ice
{
TxHelper tx(this);
if (s->ScheduleId == 0) {
- Modify(Schedules_insert, s->ServiceId, s->EventId, s->Title, s->Search, s->Priority, s->Early, s->Late, s->Repeats).second->execute();
+ Modify(Schedules_insert, s->ServiceId, s->EventUid, s->Title, s->Search, s->Priority, s->Early, s->Late, s->Repeats).second->execute();
s->ScheduleId = SelectScalar<int>(Schedules_insertNewId);
}
else {
- Modify(Schedules_update, s->ServiceId, s->EventId, s->Title, s->Search, s->Priority, s->Early, s->Late, s->Repeats, s->ScheduleId).second->execute();
+ Modify(Schedules_update, s->ServiceId, s->EventUid, s->Title, s->Search, s->Priority, s->Early, s->Late, s->Repeats, s->ScheduleId).second->execute();
}
DoReschedule(ice);
return s->ScheduleId;
diff --git a/p2pvr/daemon/schedules.h b/p2pvr/daemon/schedules.h
index f7075dd..2ff9e0f 100644
--- a/p2pvr/daemon/schedules.h
+++ b/p2pvr/daemon/schedules.h
@@ -11,11 +11,10 @@ class Episode;
class Showing : public IntrusivePtrBase {
public:
- Showing(unsigned int s, unsigned int e, unsigned int t, unsigned int sc, datetime start, datetime stop, int p, const Episode * ep);
+ Showing(unsigned int e, unsigned int t, unsigned int sc, datetime start, datetime stop, int p, const Episode * ep);
// Record what?
const Episode * episode;
- const unsigned int serviceId;
- const unsigned int eventId;
+ const unsigned int eventUid;
int priority;
const unsigned int scheduleId;
// Requires
diff --git a/p2pvr/daemon/si.cpp b/p2pvr/daemon/si.cpp
index 571c6b0..0c5162e 100644
--- a/p2pvr/daemon/si.cpp
+++ b/p2pvr/daemon/si.cpp
@@ -9,6 +9,7 @@
ResourceString(SI_serviceNextUsed, sql_SI_serviceNextUsed);
ResourceString(SI_servicesSelectAll, sql_SI_servicesSelectAll);
ResourceString(SI_servicesSelectById, sql_SI_servicesSelectById);
+ResourceString(SI_eventByUid, sql_SI_eventByUid);
ResourceString(SI_eventById, sql_SI_eventById);
ResourceString(SI_eventsOnNow, sql_SI_eventsOnNow);
ResourceString(SI_eventsInSchedule, sql_SI_eventsInSchedule);
@@ -100,57 +101,69 @@ SI::GetService(int id, const Ice::Current&)
return rtn.front();
}
-DVBSI::EventPtr
+P2PVR::Events
+SI::GetEvents(const P2PVR::IntSequence & eventUids, const Ice::Current &)
+{
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
+ BOOST_FOREACH(const auto & uid, eventUids){
+ cc.populate(Select(SI_eventByUid, uid).second);
+ }
+ if (rtn.size() != eventUids.size()) throw P2PVR::NotFound();
+ return rtn;
+}
+
+P2PVR::EventPtr
SI::GetEvent(int serviceId, int eventId, const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventById, serviceId, eventId).second);
if (rtn.empty()) throw P2PVR::NotFound();
return rtn.front();
}
-DVBSI::Events
+P2PVR::Events
SI::EventsOnNow(const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventsOnNow).second);
return rtn;
}
-DVBSI::Events
+P2PVR::Events
SI::EventsInRange(const Common::DateTime & from, const Common::DateTime & to, const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventsInRange, from, to).second);
return rtn;
}
-DVBSI::Events
+P2PVR::Events
SI::EventSearch(const IceUtil::Optional<std::string> & keywords, const IceUtil::Optional<Ice::Int> & serviceId, const IceUtil::Optional<Common::DateTime> & from, const IceUtil::Optional<Common::DateTime> & to, const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventSearch, from, to, serviceId, serviceId, keywords, keywords, keywords, keywords).second);
return rtn;
}
-DVBSI::Events
+P2PVR::Events
SI::EventsInSchedules(const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventsInSchedules).second);
return rtn;
}
-DVBSI::Events
+P2PVR::Events
SI::EventsInSchedule(int scheduleId, const Ice::Current &)
{
- DVBSI::Events rtn;
- SqlContainerCreator<DVBSI::Events, DVBSI::Event> cc(rtn);
+ P2PVR::Events rtn;
+ SqlContainerCreator<P2PVR::Events, P2PVR::Event> cc(rtn);
cc.populate(Select(SI_eventsInSchedule, scheduleId).second);
return rtn;
}
diff --git a/p2pvr/daemon/si.h b/p2pvr/daemon/si.h
index dd48d77..21b78e1 100644
--- a/p2pvr/daemon/si.h
+++ b/p2pvr/daemon/si.h
@@ -14,12 +14,13 @@ class SI : public P2PVR::SI, public DatabaseClient {
DVBSI::ServiceList GetServices(const Ice::Current &);
DVBSI::ServicePtr GetService(int id, const Ice::Current &);
- DVBSI::EventPtr GetEvent(int serviceId, int eventId, const Ice::Current &);
- DVBSI::Events EventsOnNow(const Ice::Current &);
- DVBSI::Events EventsInSchedules(const Ice::Current &);
- DVBSI::Events EventsInSchedule(int scheduleId, const Ice::Current &);
- DVBSI::Events EventsInRange(const Common::DateTime &, const Common::DateTime &, const Ice::Current &);
- DVBSI::Events EventSearch(const IceUtil::Optional<std::string> & keywords, const IceUtil::Optional<Ice::Int> & serviceId, const IceUtil::Optional<Common::DateTime> & from, const IceUtil::Optional<Common::DateTime> & to, const Ice::Current &);
+ P2PVR::Events GetEvents(const P2PVR::IntSequence & eventUids, const Ice::Current &);
+ P2PVR::EventPtr GetEvent(int serviceId, int eventId, const Ice::Current &);
+ P2PVR::Events EventsOnNow(const Ice::Current &);
+ P2PVR::Events EventsInSchedules(const Ice::Current &);
+ P2PVR::Events EventsInSchedule(int scheduleId, const Ice::Current &);
+ P2PVR::Events EventsInRange(const Common::DateTime &, const Common::DateTime &, const Ice::Current &);
+ P2PVR::Events EventSearch(const IceUtil::Optional<std::string> & keywords, const IceUtil::Optional<Ice::Int> & serviceId, const IceUtil::Optional<Common::DateTime> & from, const IceUtil::Optional<Common::DateTime> & to, const Ice::Current &);
};
#endif
diff --git a/p2pvr/daemon/sql/Maint_pruneEvents.sql b/p2pvr/daemon/sql/Maint_pruneEvents.sql
new file mode 100644
index 0000000..b6f1d1b
--- /dev/null
+++ b/p2pvr/daemon/sql/Maint_pruneEvents.sql
@@ -0,0 +1,4 @@
+DELETE FROM events e
+WHERE e.eventuid NOT IN (SELECT eventuid FROM recorded)
+AND e.eventuid NOT IN (SELECT eventuid FROM recordings)
+AND NOT current
diff --git a/p2pvr/daemon/sql/Recordings_getAll.sql b/p2pvr/daemon/sql/Recordings_getAll.sql
index c0a096c..3c3ff51 100644
--- a/p2pvr/daemon/sql/Recordings_getAll.sql
+++ b/p2pvr/daemon/sql/Recordings_getAll.sql
@@ -1,3 +1,3 @@
-SELECT recordingId, storageAddress, guid, scheduleId, title, subtitle, description, startTime, duration
+SELECT recordingId, storageAddress, guid, scheduleId, eventUid
FROM recordings r
-ORDER BY startTime, title, subtitle
+ORDER BY recordingId
diff --git a/p2pvr/daemon/sql/Recordings_insert.sql b/p2pvr/daemon/sql/Recordings_insert.sql
index dfe2ccc..ba0b9e2 100644
--- a/p2pvr/daemon/sql/Recordings_insert.sql
+++ b/p2pvr/daemon/sql/Recordings_insert.sql
@@ -1,2 +1,2 @@
-INSERT INTO recordings(storageAddress, guid, scheduleId, title, subtitle, description, startTime, duration)
-VALUES(?, ?, ?, ?, ?, ?, ?, ?)
+INSERT INTO recordings(storageAddress, guid, scheduleId, eventUid)
+VALUES(?, ?, ?, ?)
diff --git a/p2pvr/daemon/sql/SI_eventById.sql b/p2pvr/daemon/sql/SI_eventById.sql
index f0e028d..b751ad6 100644
--- a/p2pvr/daemon/sql/SI_eventById.sql
+++ b/p2pvr/daemon/sql/SI_eventById.sql
@@ -1,4 +1,5 @@
-select e.serviceid,
+select
+ e.serviceid,
e.eventid,
e.title,
e.titlelang,
@@ -21,8 +22,11 @@ select e.serviceid,
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e
-where serviceid = ?
+where serviceid = ?
and eventid = ?
+and current
diff --git a/p2pvr/daemon/sql/SI_eventByUid.sql b/p2pvr/daemon/sql/SI_eventByUid.sql
new file mode 100644
index 0000000..1d559ec
--- /dev/null
+++ b/p2pvr/daemon/sql/SI_eventByUid.sql
@@ -0,0 +1,30 @@
+select
+ e.serviceid,
+ e.eventid,
+ e.title,
+ e.titlelang,
+ e.subtitle,
+ e.description,
+ e.descriptionlang,
+ e.videoaspect,
+ e.videoframerate,
+ e.videohd,
+ e.audiochannels,
+ e.audiolanguage,
+ e.subtitlelanguage,
+ e.category,
+ e.subcategory,
+ e.usercategory,
+ e.dvbrating,
+ e.starttime,
+ e.stoptime,
+ e.episode,
+ e.episodes,
+ e.year,
+ e.flags,
+ e.season,
+ e.eventuid,
+ e.current
+from events e
+where eventuid = ?
+
diff --git a/p2pvr/daemon/sql/SI_eventSearch.sql b/p2pvr/daemon/sql/SI_eventSearch.sql
index 7ff0cf7..ffbe93f 100644
--- a/p2pvr/daemon/sql/SI_eventSearch.sql
+++ b/p2pvr/daemon/sql/SI_eventSearch.sql
@@ -22,11 +22,14 @@ select
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e
where tsrange(?, ?, '[)') && tsrange(e.starttime, e.stoptime)
and (e.serviceId = ? or ?::int is null)
and (event_tsvector(e) @@ plainto_tsquery(?) or ?::text is null)
+and current
order by
max(ts_rank(event_tsvector(e), plainto_tsquery(?))) over(partition by title) desc,
max(ts_rank(event_tsvector(e), plainto_tsquery(?))) over(partition by title, subtitle, description) desc,
diff --git a/p2pvr/daemon/sql/SI_eventsInRange.sql b/p2pvr/daemon/sql/SI_eventsInRange.sql
index 0a2d6de..1d0eb17 100644
--- a/p2pvr/daemon/sql/SI_eventsInRange.sql
+++ b/p2pvr/daemon/sql/SI_eventsInRange.sql
@@ -1,4 +1,5 @@
-select e.serviceid,
+select
+ e.serviceid,
e.eventid,
e.title,
e.titlelang,
@@ -21,8 +22,11 @@ select e.serviceid,
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e
where tsrange(?, ?, '[)') && tsrange(e.starttime, e.stoptime)
+and current
order by e.serviceid, e.starttime
diff --git a/p2pvr/daemon/sql/SI_eventsInSchedule.sql b/p2pvr/daemon/sql/SI_eventsInSchedule.sql
index 3f919a5..72ae26e 100644
--- a/p2pvr/daemon/sql/SI_eventsInSchedule.sql
+++ b/p2pvr/daemon/sql/SI_eventsInSchedule.sql
@@ -1,4 +1,5 @@
-select e.serviceid,
+select
+ e.serviceid,
e.eventid,
e.title,
e.titlelang,
@@ -21,10 +22,12 @@ select e.serviceid,
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e, record r
-where e.serviceid = r.serviceid
-and e.eventid = r.eventid
+where e.eventuid = r.eventuid
and r.scheduleid = ?
+and e.current
order by e.serviceid, e.starttime
diff --git a/p2pvr/daemon/sql/SI_eventsInSchedules.sql b/p2pvr/daemon/sql/SI_eventsInSchedules.sql
index bd4637a..880b28a 100644
--- a/p2pvr/daemon/sql/SI_eventsInSchedules.sql
+++ b/p2pvr/daemon/sql/SI_eventsInSchedules.sql
@@ -1,4 +1,5 @@
-select e.serviceid,
+select
+ e.serviceid,
e.eventid,
e.title,
e.titlelang,
@@ -21,9 +22,11 @@ select e.serviceid,
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e, record r
-where e.serviceid = r.serviceid
-and e.eventid = r.eventid
+where e.eventuid = r.eventuid
+and current
order by e.serviceid, e.starttime
diff --git a/p2pvr/daemon/sql/SI_eventsOnNow.sql b/p2pvr/daemon/sql/SI_eventsOnNow.sql
index 36760b4..391e8de 100644
--- a/p2pvr/daemon/sql/SI_eventsOnNow.sql
+++ b/p2pvr/daemon/sql/SI_eventsOnNow.sql
@@ -1,4 +1,5 @@
-select e.serviceid,
+select
+ e.serviceid,
e.eventid,
e.title,
e.titlelang,
@@ -21,7 +22,10 @@ select e.serviceid,
e.episodes,
e.year,
e.flags,
- e.season
+ e.season,
+ e.eventuid,
+ e.current
from events e
where now()::timestamp without time zone <@ tsrange(e.starttime, e.stoptime)
+and current
order by e.serviceid
diff --git a/p2pvr/daemon/sql/SI_serviceNextUsed.sql b/p2pvr/daemon/sql/SI_serviceNextUsed.sql
index 8e906ad..1bf2053 100644
--- a/p2pvr/daemon/sql/SI_serviceNextUsed.sql
+++ b/p2pvr/daemon/sql/SI_serviceNextUsed.sql
@@ -1,12 +1,11 @@
SELECT dd.*
FROM delivery_dvbt dd, services s
- LEFT OUTER JOIN record r
- ON r.serviceid = s.serviceid
- AND r.recordstatus = 0
LEFT OUTER JOIN events e
- ON r.eventid = e.eventid
- AND r.serviceid = e.serviceid
+ ON s.serviceid = e.serviceid
AND e.starttime > NOW()
+ LEFT OUTER JOIN record r
+ ON r.eventuid = e.eventuid
+ AND r.recordstatus = 0
WHERE dd.transportstreamid = s.transportstreamid
ORDER BY e.starttime, s.serviceid
LIMIT 1
diff --git a/p2pvr/daemon/sql/Schedules_GetCandidates.sql b/p2pvr/daemon/sql/Schedules_GetCandidates.sql
index 8e8b15e..0bb7bd8 100644
--- a/p2pvr/daemon/sql/Schedules_GetCandidates.sql
+++ b/p2pvr/daemon/sql/Schedules_GetCandidates.sql
@@ -1,25 +1,26 @@
-select what, serviceid, eventid, transportstreamid,
+select what, eventuid, transportstreamid,
starttime - early starttime, stoptime + late stoptime,
priority, scheduleid
from (
- select (e.title, e.subtitle, e.description)::text what, e.serviceid, e.eventid, sv.transportstreamid,
+ select (e.title, e.subtitle, e.description)::text what, e.eventuid, sv.transportstreamid,
e.starttime, e.stoptime - interval '1 second' stoptime,
s.early, s.late, s.scheduleid, s.priority,
- rank() over(partition by e.serviceid, e.eventid, sv.serviceid order by s.priority desc, s.scheduleid) schedulerank
+ rank() over(partition by e.eventuid, sv.serviceid order by s.priority desc, s.scheduleid) schedulerank
from services sv, events e, schedules s
where (s.serviceid is null or s.serviceid = e.serviceid)
and (s.title is null or lower(s.title) = lower(e.title))
- and (s.eventid is null or s.eventid = e.eventid)
+ and (s.eventuid is null or s.eventuid = e.eventuid)
and (s.search is null or event_tsvector(e) @@ plainto_tsquery(s.search))
and sv.serviceid = e.serviceid
and e.stoptime > now()
and not exists (
select 1
- from recorded r
- where lower(e.title) = lower(r.title)
- and coalesce(lower(e.subtitle), '') = coalesce(lower(r.subtitle), '')
- and ts_rank(to_tsvector(e.description), plainto_tsquery(r.description)) +
- ts_rank(to_tsvector(r.description), plainto_tsquery(e.description)) > 1)) e
+ from recorded r, events re
+ where r.eventuid = re.eventuid
+ and lower(e.title) = lower(re.title)
+ and coalesce(lower(e.subtitle), '') = coalesce(lower(re.subtitle), '')
+ and ts_rank(to_tsvector(e.description), plainto_tsquery(re.description)) +
+ ts_rank(to_tsvector(re.description), plainto_tsquery(e.description)) > 1)) e
where e.schedulerank = 1
order by e.priority desc, e.what, e.transportstreamid, e.starttime
diff --git a/p2pvr/daemon/sql/Schedules_insert.sql b/p2pvr/daemon/sql/Schedules_insert.sql
index 100e78b..70c95bd 100644
--- a/p2pvr/daemon/sql/Schedules_insert.sql
+++ b/p2pvr/daemon/sql/Schedules_insert.sql
@@ -1,2 +1,2 @@
-INSERT INTO schedules(serviceId, eventId, title, search, priority, early, late, repeats)
+INSERT INTO schedules(serviceId, eventUid, title, search, priority, early, late, repeats)
VALUES(?, ?, ?, ?, ?, ?, ?, ?)
diff --git a/p2pvr/daemon/sql/Schedules_scheduledToRecord.sql b/p2pvr/daemon/sql/Schedules_scheduledToRecord.sql
index 3874c37..09e9b4c 100644
--- a/p2pvr/daemon/sql/Schedules_scheduledToRecord.sql
+++ b/p2pvr/daemon/sql/Schedules_scheduledToRecord.sql
@@ -1,8 +1,7 @@
-SELECT r.serviceid, r.eventid, r.scheduleid
+SELECT e.serviceid, e.eventid, r.scheduleid
FROM record r, events e, schedules s
WHERE recordstatus = 0
-AND r.serviceid = e.serviceid
-AND r.eventid = e.eventid
+AND r.eventuid = e.eventuid
AND r.scheduleid = s.scheduleid
AND e.stoptime + s.late > NOW()
ORDER BY e.starttime, e.serviceid
diff --git a/p2pvr/daemon/sql/Schedules_selectAll.sql b/p2pvr/daemon/sql/Schedules_selectAll.sql
index e9e500e..56778a9 100644
--- a/p2pvr/daemon/sql/Schedules_selectAll.sql
+++ b/p2pvr/daemon/sql/Schedules_selectAll.sql
@@ -1,3 +1,3 @@
-SELECT scheduleid, serviceid, eventid, title, search, priority, early, late, repeats
+SELECT scheduleid, serviceid, eventuid, title, search, priority, early, late, repeats
FROM schedules
ORDER BY scheduleId
diff --git a/p2pvr/daemon/sql/Schedules_selectById.sql b/p2pvr/daemon/sql/Schedules_selectById.sql
index 4990418..291398c 100644
--- a/p2pvr/daemon/sql/Schedules_selectById.sql
+++ b/p2pvr/daemon/sql/Schedules_selectById.sql
@@ -1,5 +1,4 @@
-SELECT scheduleid, serviceid, eventid, title, search, priority, early, late, repeats
+SELECT scheduleid, serviceid, eventuid, title, search, priority, early, late, repeats
FROM schedules
WHERE scheduleid = ?
-ORDER BY scheduleId
diff --git a/p2pvr/daemon/sql/Schedules_update.sql b/p2pvr/daemon/sql/Schedules_update.sql
index 56c9531..cf3ce49 100644
--- a/p2pvr/daemon/sql/Schedules_update.sql
+++ b/p2pvr/daemon/sql/Schedules_update.sql
@@ -1,6 +1,6 @@
UPDATE schedules SET
serviceId = ?,
- eventId = ?,
+ eventUid = ?,
title = ?,
search = ?,
priority = ?,
diff --git a/p2pvr/daemon/unittests/Jamfile.jam b/p2pvr/daemon/unittests/Jamfile.jam
index d0d704d..e41b164 100644
--- a/p2pvr/daemon/unittests/Jamfile.jam
+++ b/p2pvr/daemon/unittests/Jamfile.jam
@@ -16,6 +16,7 @@ unit-test testp2ice :
<library>../..//p2ice
<library>../..//p2ut
<dependency>../../ice//p2pvrice
+ <dependency>../../lib//p2pvrlib
<dependency>../../p2comp//p2pvrp2comp
<library>boost_system
<library>boost_filesystem
@@ -24,7 +25,7 @@ unit-test testp2ice :
;
unit-test testMaint :
- testMaint.cpp
+ testMaint.cpp mockDevices.cpp mockScheduler.cpp
:
<define>BOOST_TEST_DYN_LINK
<library>../..//p2common
@@ -43,4 +44,61 @@ unit-test testMaint :
<define>ROOT=\"$(me)\"
;
+unit-test testRecordings :
+ testRecordings.cpp
+ :
+ <define>BOOST_TEST_DYN_LINK
+ <library>../..//p2common
+ <library>../..//p2basics
+ <library>../..//p2lib
+ <library>../..//p2ice
+ <library>../..//p2xml
+ <library>../..//p2ut
+ <library>..//p2pvrdaemon
+ <library>IceUtil
+ <library>Ice
+ <library>boost_system
+ <library>boost_filesystem
+ <library>../..//boost_utf
+ <define>ROOT=\"$(me)\"
+ ;
+
+unit-test testSi :
+ testSi.cpp
+ :
+ <define>BOOST_TEST_DYN_LINK
+ <library>../..//p2common
+ <library>../..//p2basics
+ <library>../..//p2lib
+ <library>../..//p2ice
+ <library>../..//p2xml
+ <library>../..//p2ut
+ <library>..//p2pvrdaemon
+ <library>IceUtil
+ <library>Ice
+ <library>boost_system
+ <library>boost_filesystem
+ <library>../..//boost_utf
+ <define>ROOT=\"$(me)\"
+ ;
+
+unit-test testSched :
+ testSched.cpp mockDevices.cpp mockRecorder.cpp
+ :
+ <define>BOOST_TEST_DYN_LINK
+ <library>../..//p2common
+ <library>../..//p2basics
+ <library>../..//p2lib
+ <library>../..//p2ice
+ <library>../..//p2xml
+ <library>../..//p2ut
+ <library>..//p2pvrdaemon
+ <library>IceUtil
+ <library>Ice
+ <library>boost_system
+ <library>boost_filesystem
+ <library>../../devices//p2pvrMockTuner
+ <library>../..//boost_utf
+ <define>ROOT=\"$(me)\"
+ ;
diff --git a/p2pvr/daemon/unittests/mockDevices.cpp b/p2pvr/daemon/unittests/mockDevices.cpp
new file mode 100644
index 0000000..7c3dc2c
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockDevices.cpp
@@ -0,0 +1,29 @@
+#include "mockDevices.h"
+#include <mockTuner.h>
+#include <Ice/ObjectAdapter.h>
+
+P2PVR::TunerPrx MockDevices::GetTunerSpecific(const DVBSI::DeliveryPtr&, const Ice::Current & ice)
+{
+ return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
+}
+
+P2PVR::TunerPrx MockDevices::GetTunerAny(Ice::Short, const DVBSI::DeliveryPtr&, const Ice::Current & ice)
+{
+ return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
+}
+
+P2PVR::PrivateTunerPrx MockDevices::GetPrivateTuner(Ice::Short, const Ice::Current & ice)
+{
+ return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
+}
+
+void MockDevices::ReleaseTuner(const P2PVR::TunerPrx & tuner, const Ice::Current & ice)
+{
+ ice.adapter->remove(tuner->ice_getIdentity());
+}
+
+Ice::Int MockDevices::TunerCount(const Ice::Current&)
+{
+ return 1;
+}
+
diff --git a/p2pvr/daemon/unittests/mockDevices.h b/p2pvr/daemon/unittests/mockDevices.h
new file mode 100644
index 0000000..59d1b50
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockDevices.h
@@ -0,0 +1,16 @@
+#ifndef P2PVR_MOCKS_DEVICES_H
+#define P2PVR_MOCKS_DEVICES_H
+
+#include <dvb.h>
+
+class MockDevices : public P2PVR::Devices {
+ public:
+ P2PVR::TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr&, const Ice::Current & ice) override;
+ P2PVR::TunerPrx GetTunerAny(Ice::Short, const DVBSI::DeliveryPtr&, const Ice::Current & ice) override;
+ P2PVR::PrivateTunerPrx GetPrivateTuner(Ice::Short, const Ice::Current & ice) override;
+ void ReleaseTuner(const P2PVR::TunerPrx & tuner, const Ice::Current & ice) override;
+ Ice::Int TunerCount(const Ice::Current&) override;
+};
+
+#endif
+
diff --git a/p2pvr/daemon/unittests/mockRecorder.cpp b/p2pvr/daemon/unittests/mockRecorder.cpp
new file mode 100644
index 0000000..0796aba
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockRecorder.cpp
@@ -0,0 +1,8 @@
+#include "mockRecorder.h"
+
+void
+MockRecorder::RefreshSchedules(const Ice::Current &)
+{
+
+}
+
diff --git a/p2pvr/daemon/unittests/mockRecorder.h b/p2pvr/daemon/unittests/mockRecorder.h
new file mode 100644
index 0000000..85f747b
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockRecorder.h
@@ -0,0 +1,12 @@
+#ifndef P2PVR_MOCKS_RECORDER_H
+#define P2PVR_MOCKS_RECORDER_H
+
+#include <p2pvr.h>
+
+class MockRecorder : public P2PVR::Recorder {
+ public:
+ void RefreshSchedules(const Ice::Current &) override;
+};
+
+#endif
+
diff --git a/p2pvr/daemon/unittests/mockScheduler.cpp b/p2pvr/daemon/unittests/mockScheduler.cpp
new file mode 100644
index 0000000..2677df7
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockScheduler.cpp
@@ -0,0 +1,36 @@
+#include "mockScheduler.h"
+
+void
+MockScheduler::DoReschedule(const::Ice::Current &)
+{
+}
+
+void
+MockScheduler::DeleteSchedule(Ice::Int, const Ice::Current &)
+{
+}
+
+P2PVR::SchedulePtr
+MockScheduler::GetSchedule(::Ice::Int, const::Ice::Current &)
+{
+ return P2PVR::SchedulePtr();
+}
+
+P2PVR::ScheduleList
+MockScheduler::GetSchedules(const::Ice::Current &)
+{
+ return P2PVR::ScheduleList();
+}
+
+P2PVR::ScheduledToRecordList
+MockScheduler::GetScheduledToRecord(const::Ice::Current &)
+{
+ return P2PVR::ScheduledToRecordList();
+}
+
+Ice::Int
+MockScheduler::UpdateSchedule(const::P2PVR::SchedulePtr &, const::Ice::Current &)
+{
+ return 0;
+}
+
diff --git a/p2pvr/daemon/unittests/mockScheduler.h b/p2pvr/daemon/unittests/mockScheduler.h
new file mode 100644
index 0000000..9176bb6
--- /dev/null
+++ b/p2pvr/daemon/unittests/mockScheduler.h
@@ -0,0 +1,17 @@
+#ifndef P2PVR_MOCKS_SCHEDULER_H
+#define P2PVR_MOCKS_SCHEDULER_H
+
+#include <p2pvr.h>
+
+class MockScheduler : public P2PVR::Schedules {
+ public:
+ void DoReschedule(const ::Ice::Current&) override;
+ void DeleteSchedule(Ice::Int, const Ice::Current&) override;
+ P2PVR::SchedulePtr GetSchedule(::Ice::Int, const ::Ice::Current&) override;
+ P2PVR::ScheduleList GetSchedules(const ::Ice::Current&) override;
+ P2PVR::ScheduledToRecordList GetScheduledToRecord(const ::Ice::Current&) override;
+ Ice::Int UpdateSchedule(const ::P2PVR::SchedulePtr&, const ::Ice::Current&) override;
+};
+
+#endif
+
diff --git a/p2pvr/daemon/unittests/testMaint.cpp b/p2pvr/daemon/unittests/testMaint.cpp
index 139284c..10f365e 100644
--- a/p2pvr/daemon/unittests/testMaint.cpp
+++ b/p2pvr/daemon/unittests/testMaint.cpp
@@ -7,100 +7,90 @@
#include <scopeObject.h>
#include <maintenance.h>
#include <mockTuner.h>
+#include "mockDevices.h"
+#include "mockScheduler.h"
#include <si.h>
+#include <recordings.h>
#include <linux/dvb/frontend.h>
+#include <definedDirs.h>
-#define XSTR(s) STR(s)
-#define STR(s) #s
-const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path();
-const auto componentdir = bindir.parent_path() / "component";
-const boost::filesystem::path root(XSTR(ROOT));
-
-class MockDevices : public P2PVR::Devices {
+class Core {
public:
- P2PVR::TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr&, const Ice::Current & ice) override
- {
- return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
- }
- P2PVR::TunerPrx GetTunerAny(Ice::Short, const DVBSI::DeliveryPtr&, const Ice::Current & ice) override
- {
- return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
- }
- P2PVR::PrivateTunerPrx GetPrivateTuner(Ice::Short, const Ice::Current & ice) override
- {
- return P2PVR::PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner()));
- }
- void ReleaseTuner(const P2PVR::TunerPrx & tuner, const Ice::Current & ice) override
+ Core()
{
- ice.adapter->remove(tuner->ice_getIdentity());
+ int paramCount = 0;
+ ic = Ice::initialize(paramCount, NULL);
+ auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12000");
+ TestOptionsSource::LoadTestOptions({
+ { "common.datasourceRoot", (RootDir / "datasources").string() },
+ });
+ adapter->add(new MockDevices(), ic->stringToIdentity("GlobalDevices"));
+ adapter->add(new MockScheduler(), ic->stringToIdentity("Schedules"));
+ adapter->add(new SI(), ic->stringToIdentity("SI"));
+ adapter->add(new Recordings(), ic->stringToIdentity("Recordings"));
+ adapter->add(new Maintenance(adapter, NULL), ic->stringToIdentity("Maintenance"));
+ adapter->activate();
+
+ r = P2PVR::RecordingsPrx::checkedCast(ic->stringToProxy("Recordings"));
+ BOOST_REQUIRE(r);
+ r->ice_ping();
+
+ s = P2PVR::SIPrx::checkedCast(ic->stringToProxy("SI"));
+ BOOST_REQUIRE(s);
+ s->ice_ping();
+
+ m = P2PVR::MaintenancePrx::checkedCast(ic->stringToProxy("Maintenance"));
+ BOOST_REQUIRE(m);
+ m->ice_ping();
}
- Ice::Int TunerCount(const Ice::Current&) override
+
+ ~Core()
{
- return 1;
+ ic->destroy();
}
-};
-class MockScheduler : public P2PVR::Schedules {
- public:
- void DoReschedule(const ::Ice::Current&) { }
- void DeleteSchedule(Ice::Int, const Ice::Current&) { }
- P2PVR::SchedulePtr GetSchedule(::Ice::Int, const ::Ice::Current&) { return P2PVR::SchedulePtr(); }
- P2PVR::ScheduleList GetSchedules(const ::Ice::Current&) { return P2PVR::ScheduleList(); }
- P2PVR::ScheduledToRecordList GetScheduledToRecord(const ::Ice::Current&) { return P2PVR::ScheduledToRecordList(); }
- Ice::Int UpdateSchedule(const ::P2PVR::SchedulePtr&, const ::Ice::Current&) { return 0; }
+ P2PVR::MaintenancePrx m;
+ P2PVR::RecordingsPrx r;
+ P2PVR::SIPrx s;
+
+ private:
+ Ice::CommunicatorPtr ic;
};
-static
-Ice::CommunicatorPtr
-standardConfig()
-{
- int paramCount = 0;
- Ice::CommunicatorPtr ic = Ice::initialize(paramCount, NULL);
- auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12000");
- TestOptionsSource::LoadTestOptions({
- { "common.datasourceRoot", (root / "datasources").string() },
- });
- adapter->add(new MockDevices(), ic->stringToIdentity("GlobalDevices"));
- adapter->add(new MockScheduler(), ic->stringToIdentity("Schedules"));
- adapter->add(new SI(), ic->stringToIdentity("SI"));
- adapter->add(new Maintenance(adapter, NULL), ic->stringToIdentity("Maintenance"));
- adapter->activate();
- return ic;
-}
+BOOST_FIXTURE_TEST_SUITE( MaintCore, Core )
BOOST_AUTO_TEST_CASE( update_network )
{
- auto ic = standardConfig();
- ScopeObject _([&ic]{ ic->destroy(); });
-
- auto m = P2PVR::MaintenancePrx::checkedCast(ic->stringToProxy("Maintenance"));
- BOOST_REQUIRE(m);
- m->ice_ping();
-
m->UpdateNetwork(FE_OFDM);
}
BOOST_AUTO_TEST_CASE( update_services )
{
- auto ic = standardConfig();
- ScopeObject _([&ic]{ ic->destroy(); });
-
- auto m = P2PVR::MaintenancePrx::checkedCast(ic->stringToProxy("Maintenance"));
- BOOST_REQUIRE(m);
- m->ice_ping();
-
m->UpdateServices(FE_OFDM);
}
BOOST_AUTO_TEST_CASE( update_events )
{
- auto ic = standardConfig();
- ScopeObject _([&ic]{ ic->destroy(); });
+ BOOST_CHECKPOINT("Get existing recordings");
+ auto recs = r->GetRecordings();
- auto m = P2PVR::MaintenancePrx::checkedCast(ic->stringToProxy("Maintenance"));
- BOOST_REQUIRE(m);
- m->ice_ping();
-
+ BOOST_CHECKPOINT("Delete existing recordings");
+ BOOST_FOREACH(const auto & rec, recs) {
+ r->DeleteRecording(rec->RecordingId);
+ }
+
+ BOOST_CHECKPOINT("Write first events");
+ MockTuner::SetEventsSet(0);
m->UpdateEvents(FE_OFDM);
+ BOOST_REQUIRE(s->GetEvent(14448, 27052));
+ BOOST_REQUIRE_THROW(s->GetEvent(15856, 3591), P2PVR::NotFound);
+
+ BOOST_CHECKPOINT("Write second events");
+ MockTuner::SetEventsSet(1);
+ m->UpdateEvents(FE_OFDM);
+ BOOST_REQUIRE_THROW(s->GetEvent(14448, 27052), P2PVR::NotFound);
+ BOOST_REQUIRE(s->GetEvent(15856, 3591));
}
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/p2pvr/daemon/unittests/testRecordings.cpp b/p2pvr/daemon/unittests/testRecordings.cpp
new file mode 100644
index 0000000..adfc231
--- /dev/null
+++ b/p2pvr/daemon/unittests/testRecordings.cpp
@@ -0,0 +1,74 @@
+#define BOOST_TEST_MODULE Recordings
+#include <boost/test/unit_test.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <testOptionsSource.h>
+#include <Ice/ObjectAdapter.h>
+#include <Ice/Service.h>
+#include <scopeObject.h>
+#include <maintenance.h>
+#include <mockTuner.h>
+#include <si.h>
+#include <recordings.h>
+#include <linux/dvb/frontend.h>
+#include <definedDirs.h>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/lexical_cast.hpp>
+
+class Core {
+ public:
+ Core()
+ {
+ int paramCount = 0;
+ ic = Ice::initialize(paramCount, NULL);
+ auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12001");
+ TestOptionsSource::LoadTestOptions({
+ { "common.datasourceRoot", (RootDir / "datasources").string() },
+ });
+ adapter->add(new Recordings(), ic->stringToIdentity("Recordings"));
+ adapter->add(new SI(), ic->stringToIdentity("SI"));
+ adapter->activate();
+
+ r = P2PVR::RecordingsPrx::checkedCast(ic->stringToProxy("Recordings"));
+ BOOST_REQUIRE(r);
+ r->ice_ping();
+
+ si = P2PVR::SIPrx::checkedCast(ic->stringToProxy("SI"));
+ BOOST_REQUIRE(si);
+ si->ice_ping();
+ }
+
+ ~Core()
+ {
+ ic->destroy();
+ }
+
+ P2PVR::SIPrx si;
+ P2PVR::RecordingsPrx r;
+
+ private:
+ Ice::CommunicatorPtr ic;
+};
+
+BOOST_FIXTURE_TEST_SUITE( RecCore, Core )
+
+BOOST_AUTO_TEST_CASE( recordings_get )
+{
+ r->GetRecordings();
+}
+
+BOOST_AUTO_TEST_CASE( recordings_addAndDelete )
+{
+ auto event = si->GetEvent(5696, 40124);
+ BOOST_REQUIRE(event);
+ BOOST_MESSAGE(event->Title);
+
+ auto guid = boost::lexical_cast<std::string>(boost::uuids::random_generator()());
+ auto rec = P2PVR::RecordingPtr(new P2PVR::Recording(0, "", guid, 0, event->EventUid));
+ auto id = r->NewRecording(rec);
+ r->GetRecordings();
+ r->DeleteRecording(id);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/p2pvr/daemon/unittests/testSched.cpp b/p2pvr/daemon/unittests/testSched.cpp
new file mode 100644
index 0000000..9a6134b
--- /dev/null
+++ b/p2pvr/daemon/unittests/testSched.cpp
@@ -0,0 +1,102 @@
+#define BOOST_TEST_MODULE Scheduler
+#include <boost/test/unit_test.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <testOptionsSource.h>
+#include <Ice/ObjectAdapter.h>
+#include <Ice/Service.h>
+#include <maintenance.h>
+#include <mockTuner.h>
+#include <si.h>
+#include <schedules.h>
+#include "mockDevices.h"
+#include "mockRecorder.h"
+#include <definedDirs.h>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/lexical_cast.hpp>
+#include <commonHelpers.h>
+
+class Core {
+ public:
+ Core()
+ {
+ int paramCount = 0;
+ ic = Ice::initialize(paramCount, NULL);
+ auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12003");
+ TestOptionsSource::LoadTestOptions({
+ { "common.datasourceRoot", (RootDir / "datasources").string() },
+ });
+ adapter->add(new Schedules(), ic->stringToIdentity("Schedules"));
+ adapter->add(new MockDevices(), ic->stringToIdentity("GlobalDevices"));
+ adapter->add(new MockRecorder(), ic->stringToIdentity("Recorder"));
+ adapter->activate();
+
+ sc = P2PVR::SchedulesPrx::checkedCast(ic->stringToProxy("Schedules"));
+ BOOST_REQUIRE(sc);
+ sc->ice_ping();
+ }
+
+ ~Core()
+ {
+ ic->destroy();
+ }
+
+ P2PVR::SchedulesPrx sc;
+
+ private:
+ Ice::CommunicatorPtr ic;
+};
+
+BOOST_FIXTURE_TEST_SUITE( ScCore, Core )
+
+BOOST_AUTO_TEST_CASE( sc_getSchedules )
+{
+ sc->GetSchedules();
+}
+
+BOOST_AUTO_TEST_CASE( sc_doReschedule )
+{
+ sc->DoReschedule();
+}
+
+BOOST_AUTO_TEST_CASE( sc_getScheduled )
+{
+ sc->GetScheduledToRecord();
+}
+
+BOOST_AUTO_TEST_CASE( sc_crud )
+{
+ P2PVR::SchedulePtr schedule = new P2PVR::Schedule();
+ schedule->Search = "Top Gear";
+
+ auto id = sc->UpdateSchedule(schedule);
+ BOOST_REQUIRE(id > 0);
+ schedule->ScheduleId = id;
+
+ auto fetched = sc->GetSchedule(id);
+ BOOST_REQUIRE_EQUAL(schedule->ScheduleId, fetched->ScheduleId);
+ BOOST_REQUIRE_EQUAL(*schedule->Search, *fetched->Search);
+ BOOST_REQUIRE_EQUAL(schedule->Priority, fetched->Priority);
+ BOOST_REQUIRE_EQUAL(schedule->Repeats, fetched->Repeats);
+ BOOST_REQUIRE_EQUAL(schedule->Early, fetched->Early);
+ BOOST_REQUIRE_EQUAL(schedule->Late, fetched->Late);
+
+ schedule->Search = "Top Gear Special";
+ schedule->Early.Minutes = 5;
+ schedule->Late.Minutes = 15;
+ auto updatedId = sc->UpdateSchedule(schedule);
+
+ fetched = sc->GetSchedule(id);
+ BOOST_REQUIRE_EQUAL(updatedId, id);
+ BOOST_REQUIRE_EQUAL(schedule->ScheduleId, fetched->ScheduleId);
+ BOOST_REQUIRE_EQUAL(*schedule->Search, *fetched->Search);
+ BOOST_REQUIRE_EQUAL(schedule->Priority, fetched->Priority);
+ BOOST_REQUIRE_EQUAL(schedule->Repeats, fetched->Repeats);
+ BOOST_REQUIRE_EQUAL(schedule->Early, fetched->Early);
+ BOOST_REQUIRE_EQUAL(schedule->Late, fetched->Late);
+
+ sc->DeleteSchedule(fetched->ScheduleId);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/p2pvr/daemon/unittests/testSi.cpp b/p2pvr/daemon/unittests/testSi.cpp
new file mode 100644
index 0000000..d191b38
--- /dev/null
+++ b/p2pvr/daemon/unittests/testSi.cpp
@@ -0,0 +1,105 @@
+#define BOOST_TEST_MODULE SI
+#include <boost/test/unit_test.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <testOptionsSource.h>
+#include <Ice/ObjectAdapter.h>
+#include <Ice/Service.h>
+#include <maintenance.h>
+#include <mockTuner.h>
+#include <si.h>
+#include <linux/dvb/frontend.h>
+#include <definedDirs.h>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/lexical_cast.hpp>
+
+class Core {
+ public:
+ Core()
+ {
+ int paramCount = 0;
+ ic = Ice::initialize(paramCount, NULL);
+ auto adapter = ic->createObjectAdapterWithEndpoints("Adp", "tcp -p 12002");
+ TestOptionsSource::LoadTestOptions({
+ { "common.datasourceRoot", (RootDir / "datasources").string() },
+ });
+ adapter->add(new SI(), ic->stringToIdentity("SI"));
+ adapter->activate();
+
+ si = P2PVR::SIPrx::checkedCast(ic->stringToProxy("SI"));
+ BOOST_REQUIRE(si);
+ si->ice_ping();
+ }
+
+ ~Core()
+ {
+ ic->destroy();
+ }
+
+ P2PVR::SIPrx si;
+
+ private:
+ Ice::CommunicatorPtr ic;
+};
+
+BOOST_FIXTURE_TEST_SUITE( SiCore, Core )
+
+BOOST_AUTO_TEST_CASE ( si_getEvents )
+{
+ // Get an event known to exist so we can use its uid
+ auto event = si->GetEvent(23968, 4378);
+ BOOST_REQUIRE(event);
+
+ auto events = si->GetEvents({ event->EventUid });
+ BOOST_REQUIRE_EQUAL(events.size(), 1);
+ BOOST_REQUIRE_EQUAL(events.front()->ServiceId, 23968);
+ BOOST_REQUIRE_EQUAL(events.front()->EventId, 4378);
+}
+
+BOOST_AUTO_TEST_CASE ( si_getEvents_missing )
+{
+ BOOST_REQUIRE_THROW(si->GetEvents({ 0 }), P2PVR::NotFound);
+}
+
+BOOST_AUTO_TEST_CASE( si_getEvent )
+{
+ auto event = si->GetEvent(23968, 4378);
+ BOOST_REQUIRE(event);
+ BOOST_REQUIRE_EQUAL(event->Title, "Timothy Goes to School");
+ BOOST_REQUIRE_EQUAL(event->Current, true);
+}
+
+BOOST_AUTO_TEST_CASE( si_getEventsOnNow )
+{
+ si->EventsOnNow();
+}
+
+BOOST_AUTO_TEST_CASE( si_getEventsInSched )
+{
+ si->EventsInSchedule(0);
+}
+
+BOOST_AUTO_TEST_CASE( si_getEventsInScheds )
+{
+ si->EventsInSchedules();
+}
+
+BOOST_AUTO_TEST_CASE( si_getEventsInRange )
+{
+ si->EventsInRange(Common::DateTime {2014, 12, 19, 3, 0}, Common::DateTime {2014, 12, 20, 3, 0});
+}
+
+BOOST_AUTO_TEST_CASE( si_getEventSearch )
+{
+ si->EventSearch("Top Gear", IceUtil::Optional< ::Ice::Int >(),
+ IceUtil::Optional<Common::DateTime>(), IceUtil::Optional<Common::DateTime>());
+ si->EventSearch("Top Gear", 22272,
+ IceUtil::Optional<Common::DateTime>(), IceUtil::Optional<Common::DateTime>());
+ si->EventSearch("Top Gear", 22272,
+ Common::DateTime {2014, 12, 19, 3, 0}, IceUtil::Optional<Common::DateTime>());
+ si->EventSearch("Top Gear", 22272,
+ Common::DateTime {2014, 12, 19, 3, 0}, Common::DateTime {2014, 12, 20, 3, 0});
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/p2pvr/daemon/unittests/testp2ice.cpp b/p2pvr/daemon/unittests/testp2ice.cpp
index 9f9e9a8..23fcbdc 100644
--- a/p2pvr/daemon/unittests/testp2ice.cpp
+++ b/p2pvr/daemon/unittests/testp2ice.cpp
@@ -2,18 +2,37 @@
#include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp>
#include <testOptionsSource.h>
+#include <definedDirs.h>
+#include <sourceObject.h>
-#define XSTR(s) STR(s)
-#define STR(s) #s
-const auto bindir = boost::filesystem::canonical("/proc/self/exe").parent_path();
-const boost::filesystem::path variant = bindir.leaf();
-const boost::filesystem::path compiler = bindir.parent_path().leaf();
-const boost::filesystem::path root = boost::filesystem::path(XSTR(ROOT)).parent_path().parent_path();
+const boost::filesystem::path variant = BinDir.leaf();
+const boost::filesystem::path compiler = BinDir.parent_path().leaf();
+const boost::filesystem::path root = RootDir.parent_path().parent_path();
const boost::filesystem::path iceroot = root / "ice";
+static
+void
+commonTests()
+{
+ BOOST_REQUIRE(ElementLoader::getFor("p2pvrrecordingstream"));
+ BOOST_REQUIRE(ElementLoader::getFor("p2pvrservicestream"));
+ BOOST_REQUIRE(ElementLoader::getFor("P2PVR-SI-GetEvent"));
+}
+
+static
+void
+unloadTests()
+{
+ BOOST_REQUIRE_THROW(ElementLoader::getFor("P2PVR-SI-GetEvent"), NotSupported);
+ // Known issue, these *should* unload, but for some reason, don't.
+ BOOST_WARN_THROW(ElementLoader::getFor("p2pvrrecordingstream"), NotSupported);
+ BOOST_WARN_THROW(ElementLoader::getFor("p2pvrservicestream"), NotSupported);
+}
BOOST_AUTO_TEST_CASE( compile_client_clientOnly )
{
+ TestOptionsSource::LoadTestOptions({ });
+
const std::string tmpdir = "/tmp/ut/p2pvr.slice";
BOOST_TEST_CHECKPOINT("Clean up");
boost::filesystem::remove_all(tmpdir);
@@ -23,13 +42,15 @@ BOOST_AUTO_TEST_CASE( compile_client_clientOnly )
{ "ice.compile.tmpdir", tmpdir },
{ "ice.client.slicerclient", (iceroot / "common.ice").string() },
{ "library", (root / "ice" / "bin" / compiler / variant / "slicer-yes" / "libp2pvrice.so").string() },
+ { "library", (root / "dvb" / "bin" / compiler / variant / "libp2pvrdvb.so").string() },
+ { "library", (root / "lib" / "bin" / compiler / variant / "libp2pvrlib.so").string() },
{ "library", (root / "p2comp" / "bin" / compiler / variant / "libp2pvrp2comp.so").string() },
{ "ice.client.slicerclient", (iceroot / "dvbsi.ice").string() },
{ "ice.client.slicerclient", (iceroot / "dvb.ice").string() },
{ "ice.client.slicerclient", (iceroot / "p2pvr.ice").string() },
});
- //commonTests();
+ commonTests();
TestOptionsSource::LoadTestOptions({ });
- //unloadTests();
+ unloadTests();
}
diff --git a/p2pvr/datasources/schema.sql b/p2pvr/datasources/schema.sql
index 393325d..5e0612f 100644
--- a/p2pvr/datasources/schema.sql
+++ b/p2pvr/datasources/schema.sql
@@ -57,7 +57,9 @@ CREATE TABLE events (
episodes smallint,
year smallint,
flags text,
- season integer
+ season integer,
+ eventuid integer NOT NULL,
+ current boolean DEFAULT true NOT NULL
);
@@ -128,6 +130,25 @@ CREATE TABLE delivery_dvbt (
--
+-- Name: events_eventuid_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE events_eventuid_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: events_eventuid_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE events_eventuid_seq OWNED BY events.eventuid;
+
+
+--
-- Name: networks; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@@ -142,8 +163,7 @@ CREATE TABLE networks (
--
CREATE TABLE record (
- serviceid integer NOT NULL,
- eventid integer NOT NULL,
+ eventuid integer NOT NULL,
recordstatus integer NOT NULL,
recordingstatus integer DEFAULT 0 NOT NULL,
scheduleid integer NOT NULL
@@ -157,11 +177,7 @@ CREATE TABLE record (
CREATE TABLE recorded (
recordedid integer NOT NULL,
scheduleid integer,
- title text,
- subtitle text,
- description text,
- starttime timestamp without time zone NOT NULL,
- duration interval NOT NULL
+ eventuid integer NOT NULL
);
@@ -193,11 +209,7 @@ CREATE TABLE recordings (
storageaddress text NOT NULL,
guid text NOT NULL,
scheduleid integer NOT NULL,
- title text,
- subtitle text,
- description text,
- starttime timestamp without time zone NOT NULL,
- duration interval NOT NULL
+ eventuid integer NOT NULL
);
@@ -227,7 +239,7 @@ ALTER SEQUENCE recordings_recordingid_seq OWNED BY recordings.recordingid;
CREATE TABLE schedules (
scheduleid integer NOT NULL,
serviceid integer,
- eventid integer,
+ eventuid integer,
title text,
search text,
priority integer DEFAULT 0 NOT NULL,
@@ -270,7 +282,7 @@ CREATE TABLE services (
eitschedule boolean,
eitpresentfollowing boolean,
freecamode boolean,
- transportstreamid integer NOT NULL
+ transportstreamid integer
);
@@ -286,6 +298,13 @@ CREATE TABLE transportstreams (
--
+-- Name: eventuid; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY events ALTER COLUMN eventuid SET DEFAULT nextval('events_eventuid_seq'::regclass);
+
+
+--
-- Name: recordedid; Type: DEFAULT; Schema: public; Owner: -
--
@@ -335,7 +354,7 @@ ALTER TABLE ONLY delivery_dvbt
--
ALTER TABLE ONLY events
- ADD CONSTRAINT pk_events PRIMARY KEY (serviceid, eventid);
+ ADD CONSTRAINT pk_events PRIMARY KEY (eventuid);
--
@@ -367,7 +386,7 @@ ALTER TABLE ONLY recordings
--
ALTER TABLE ONLY record
- ADD CONSTRAINT pk_records PRIMARY KEY (serviceid, eventid);
+ ADD CONSTRAINT pk_records PRIMARY KEY (eventuid);
--
@@ -423,20 +442,6 @@ CREATE INDEX idx_recorded_schedule ON recorded USING btree (scheduleid);
--
--- Name: idx_recorded_starttime; Type: INDEX; Schema: public; Owner: -; Tablespace:
---
-
-CREATE INDEX idx_recorded_starttime ON recorded USING btree (starttime);
-
-
---
--- Name: idx_recorded_title; Type: INDEX; Schema: public; Owner: -; Tablespace:
---
-
-CREATE INDEX idx_recorded_title ON recorded USING btree (title);
-
-
---
-- Name: idx_recordings_schedule; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
@@ -444,17 +449,10 @@ CREATE INDEX idx_recordings_schedule ON recordings USING btree (scheduleid);
--
--- Name: idx_recordings_starttime; Type: INDEX; Schema: public; Owner: -; Tablespace:
---
-
-CREATE INDEX idx_recordings_starttime ON recordings USING btree (starttime);
-
-
---
--- Name: idx_recordings_title; Type: INDEX; Schema: public; Owner: -; Tablespace:
+-- Name: uni_events_serviceevent; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
-CREATE INDEX idx_recordings_title ON recordings USING btree (title);
+CREATE UNIQUE INDEX uni_events_serviceevent ON events USING btree (serviceid, eventid) WHERE current;
--
@@ -489,6 +487,22 @@ ALTER TABLE ONLY delivery_dvbt
--
+-- Name: fk_record_eventuid; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY record
+ ADD CONSTRAINT fk_record_eventuid FOREIGN KEY (eventuid) REFERENCES events(eventuid) ON UPDATE CASCADE ON DELETE CASCADE;
+
+
+--
+-- Name: fk_recorded_eventuid; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY recorded
+ ADD CONSTRAINT fk_recorded_eventuid FOREIGN KEY (eventuid) REFERENCES events(eventuid) ON UPDATE CASCADE;
+
+
+--
-- Name: fk_recorded_schedule; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -497,11 +511,11 @@ ALTER TABLE ONLY recorded
--
--- Name: fk_records_event; Type: FK CONSTRAINT; Schema: public; Owner: -
+-- Name: fk_recordings_eventuid; Type: FK CONSTRAINT; Schema: public; Owner: -
--
-ALTER TABLE ONLY record
- ADD CONSTRAINT fk_records_event FOREIGN KEY (serviceid, eventid) REFERENCES events(serviceid, eventid) ON UPDATE CASCADE ON DELETE CASCADE;
+ALTER TABLE ONLY recordings
+ ADD CONSTRAINT fk_recordings_eventuid FOREIGN KEY (eventuid) REFERENCES events(eventuid) ON UPDATE CASCADE;
--
@@ -517,7 +531,7 @@ ALTER TABLE ONLY record
--
ALTER TABLE ONLY schedules
- ADD CONSTRAINT fk_schedule_event FOREIGN KEY (serviceid, eventid) REFERENCES events(serviceid, eventid) ON DELETE CASCADE;
+ ADD CONSTRAINT fk_schedule_event FOREIGN KEY (eventuid) REFERENCES events(eventuid) ON UPDATE CASCADE ON DELETE CASCADE;
--
@@ -533,7 +547,7 @@ ALTER TABLE ONLY schedules
--
ALTER TABLE ONLY services
- ADD CONSTRAINT fk_services_transportstreams FOREIGN KEY (transportstreamid) REFERENCES transportstreams(transportstreamid) ON UPDATE CASCADE ON DELETE CASCADE;
+ ADD CONSTRAINT fk_services_transportstreams FOREIGN KEY (transportstreamid) REFERENCES transportstreams(transportstreamid) ON UPDATE CASCADE ON DELETE SET NULL;
--
diff --git a/p2pvr/devices/mockTuner.cpp b/p2pvr/devices/mockTuner.cpp
index 335ddec..b89d533 100644
--- a/p2pvr/devices/mockTuner.cpp
+++ b/p2pvr/devices/mockTuner.cpp
@@ -23,6 +23,14 @@ ResourceFile(services);
ResourceFile(events1);
ResourceFile(events2);
+int MockTuner::eventSet = 0;
+
+void
+MockTuner::SetEventsSet(int n)
+{
+ eventSet = n;
+}
+
void MockTuner::TuneTo(const DVBSI::DeliveryPtr &, const Ice::Current&)
{
}
@@ -98,7 +106,7 @@ void MockTuner::SendProgramAssociationTable(const P2PVR::RawDataClientPrx &, con
void MockTuner::SendEventInformation(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice)
{
- DecompressAndSendPackets(events1, client, ice);
+ DecompressAndSendPackets(eventSet == 0 ? events1 : events2, client, ice);
}
int MockTuner::StartSendingTS(const P2PVR::PacketIds &, const P2PVR::RawDataClientPrx &, const Ice::Current &)
diff --git a/p2pvr/devices/mockTuner.h b/p2pvr/devices/mockTuner.h
index 220b535..31d12cb 100644
--- a/p2pvr/devices/mockTuner.h
+++ b/p2pvr/devices/mockTuner.h
@@ -6,7 +6,6 @@
class MockTuner : public P2PVR::PrivateTuner {
public:
-
void TuneTo(const DVBSI::DeliveryPtr &, const Ice::Current&);
int GetStatus(const Ice::Current&);
@@ -24,8 +23,12 @@ class MockTuner : public P2PVR::PrivateTuner {
Ice::Long GetLastUsedTime(const Ice::Current&);
+ static void SetEventsSet(int n);
+
protected:
void DecompressAndSendPackets(const Ice::ByteSeq &, const P2PVR::RawDataClientPrx &, const Ice::Current&) const;
+
+ static int eventSet;
};
#endif
diff --git a/p2pvr/ice/common.ice b/p2pvr/ice/common.ice
index 14ca155..c4be4ce 100644
--- a/p2pvr/ice/common.ice
+++ b/p2pvr/ice/common.ice
@@ -11,8 +11,8 @@ module Common {
};
struct Duration {
- short Hour;
- short Minute;
+ short Hours = 0;
+ short Minutes = 0;
};
};
diff --git a/p2pvr/ice/commonHelpers.cpp b/p2pvr/ice/commonHelpers.cpp
index 46c7fad..6ad120b 100644
--- a/p2pvr/ice/commonHelpers.cpp
+++ b/p2pvr/ice/commonHelpers.cpp
@@ -12,7 +12,7 @@ namespace Common {
boost::posix_time::time_duration operator*(const Common::Duration & d)
{
- return boost::posix_time::time_duration(d.Hour, d.Minute, 0);
+ return boost::posix_time::time_duration(d.Hours, d.Minutes, 0);
}
}
diff --git a/p2pvr/ice/commonHelpers.h b/p2pvr/ice/commonHelpers.h
index cc3cac1..3f7e57d 100644
--- a/p2pvr/ice/commonHelpers.h
+++ b/p2pvr/ice/commonHelpers.h
@@ -18,6 +18,18 @@ namespace Common {
<< ":" << std::setw(2) << std::setfill('0') << dt.Minute;
return o;
}
+
+ template<typename C, typename T>
+ std::basic_ostream<C, T> &
+ operator<<(std::basic_ostream<C, T> & o, const Common::Duration & d)
+ {
+ if (d.Hours) {
+ o << d.Hours << "hrs ";
+ }
+ o << d.Minutes << "min";
+ return o;
+ }
+
boost::posix_time::ptime operator*(const Common::DateTime &);
boost::posix_time::time_duration operator*(const Common::Duration &);
}
diff --git a/p2pvr/ice/p2pvr.ice b/p2pvr/ice/p2pvr.ice
index eb4ebbf..7f58539 100644
--- a/p2pvr/ice/p2pvr.ice
+++ b/p2pvr/ice/p2pvr.ice
@@ -7,6 +7,13 @@
module P2PVR {
["project2:type"]
+ class Event extends DVBSI::Event {
+ int EventUid;
+ bool Current = true;
+ };
+ sequence<Event> Events;
+
+ ["project2:type"]
exception NotFound { };
// Something that we have recorded.
@@ -15,27 +22,23 @@ module P2PVR {
int RecordingId;
string StorageAddress;
string Guid;
- optional(1) int ScheduleId;
- string Title;
- optional(2) string Subtitle;
- optional(3) string Description;
- Common::DateTime StartTime;
- Common::Duration Duration;
+ int ScheduleId;
+ int EventUid;
};
sequence<Recording> RecordingList;
// Something that defines what we would like to record.
["project2:type"]
class Schedule {
- int ScheduleId;
+ int ScheduleId = 0;
optional(1) int ServiceId;
- optional(2) int EventId;
+ optional(2) int EventUid;
optional(3) string Title;
optional(4) string Search;
- int Priority;
+ int Priority = 0;
Common::Duration Early;
Common::Duration Late;
- bool Repeats;
+ bool Repeats = false;
};
sequence<Schedule> ScheduleList;
@@ -43,8 +46,7 @@ module P2PVR {
["project2:type"]
class ScheduledToRecord {
int ScheduleId;
- int ServiceId;
- int EventId;
+ int EventUid;
};
sequence<ScheduledToRecord> ScheduledToRecordList;
@@ -93,6 +95,7 @@ module P2PVR {
};
sequence<DVBSI::Delivery> Deliveries;
+ sequence<int> IntSequence;
interface SI {
// Get delivery methods
idempotent Deliveries GetAllDeliveries(short type);
@@ -105,18 +108,19 @@ module P2PVR {
["project2:rows"]
idempotent DVBSI::Service GetService(int id) throws NotFound;
// Get events
+ idempotent Events GetEvents(IntSequence eventUids) throws NotFound;
["project2:rows"]
- idempotent DVBSI::Event GetEvent(int serviceId, int eventId) throws NotFound;
+ idempotent Event GetEvent(int serviceId, int eventId) throws NotFound;
["project2:rows"]
- idempotent DVBSI::Events EventsOnNow();
+ idempotent Events EventsOnNow();
["project2:rows"]
- idempotent DVBSI::Events EventsInSchedules();
+ idempotent Events EventsInSchedules();
["project2:rows"]
- idempotent DVBSI::Events EventsInSchedule(int scheduleId);
+ idempotent Events EventsInSchedule(int scheduleId);
["project2:rows"]
- idempotent DVBSI::Events EventsInRange(Common::DateTime from, Common::DateTime to);
+ idempotent Events EventsInRange(Common::DateTime from, Common::DateTime to);
["project2:rows"]
- idempotent DVBSI::Events EventSearch(optional(1) string keywords, optional(2) int serviceId, optional(3) Common::DateTime from, optional(4) Common::DateTime to);
+ idempotent Events EventSearch(optional(1) string keywords, optional(2) int serviceId, optional(3) Common::DateTime from, optional(4) Common::DateTime to);
};
interface Recorder {
diff --git a/p2pvr/lib/containerCreator.h b/p2pvr/lib/containerCreator.h
index 9804d9b..289ac9e 100644
--- a/p2pvr/lib/containerCreator.h
+++ b/p2pvr/lib/containerCreator.h
@@ -19,6 +19,9 @@ class ContainerCreator {
auto v = P(new V);
container.push_back(v);
ObjectRowState<P> rs;
+ if (rs.fields.size() != columnCount) {
+ throw std::runtime_error("Incorrent column count");
+ }
for (unsigned int c = 0; c < columnCount; c++) {
rs.fields[c] = get(c);
}
diff --git a/p2pvr/lib/dvbsiHelpers/event.cpp b/p2pvr/lib/dvbsiHelpers/event.cpp
index ca072df..4bca135 100644
--- a/p2pvr/lib/dvbsiHelpers/event.cpp
+++ b/p2pvr/lib/dvbsiHelpers/event.cpp
@@ -6,30 +6,30 @@ template<>
void
CreateColumns<DVBSI::EventPtr>(const ColumnCreator & cc)
{
- cc("serviceId", true);
- cc("eventId", true);
- cc("title", false);
- cc("titleLang", false);
- cc("subtitle", false);
- cc("description", false);
- cc("descriptionLang", false);
- cc("videoAspect", false);
- cc("videoFrameRate", false);
- cc("videoHd", false);
- cc("audioChannels", false);
- cc("audioLanguage", false);
- cc("subtitleLanguage", false);
- cc("category", false);
- cc("subCategory", false);
- cc("userCategory", false);
- cc("dvbRating", false);
- cc("startTime", false);
- cc("stopTime", false);
- cc("episode", false);
- cc("episodes", false);
- cc("year", false);
- cc("flags", false);
- cc("season", false);
+ cc("serviceId", true);
+ cc("eventId", true);
+ cc("title", false);
+ cc("titleLang", false);
+ cc("subtitle", false);
+ cc("description", false);
+ cc("descriptionLang", false);
+ cc("videoAspect", false);
+ cc("videoFrameRate", false);
+ cc("videoHd", false);
+ cc("audioChannels", false);
+ cc("audioLanguage", false);
+ cc("subtitleLanguage", false);
+ cc("category", false);
+ cc("subCategory", false);
+ cc("userCategory", false);
+ cc("dvbRating", false);
+ cc("startTime", false);
+ cc("stopTime", false);
+ cc("episode", false);
+ cc("episodes", false);
+ cc("year", false);
+ cc("flags", false);
+ cc("season", false);
}
template<>
diff --git a/p2pvr/lib/p2pvrHelpers/schedule.cpp b/p2pvr/lib/p2pvrHelpers/schedule.cpp
index f8abc1e..91815e9 100644
--- a/p2pvr/lib/p2pvrHelpers/schedule.cpp
+++ b/p2pvr/lib/p2pvrHelpers/schedule.cpp
@@ -9,7 +9,7 @@ CreateColumns<P2PVR::SchedulePtr>(const ColumnCreator & cc)
{
cc("scheduleid", true);
cc("serviceid", true);
- cc("eventid", false);
+ cc("eventuid", false);
cc("title", false);
cc("search", false);
cc("priority", false);
@@ -24,7 +24,7 @@ BindColumns(RowState & rs, const P2PVR::SchedulePtr & s)
{
rs.fields[0] << s->ScheduleId;
rs.fields[1] << s->ServiceId;
- rs.fields[2] << s->EventId;
+ rs.fields[2] << s->EventUid;
rs.fields[3] << s->Title;
rs.fields[4] << s->Search;
rs.fields[5] << s->Priority;
@@ -39,7 +39,7 @@ UnbindColumns(RowState & rs, P2PVR::SchedulePtr const & s)
{
rs.fields[0] >> s->ScheduleId;
rs.fields[1] >> s->ServiceId;
- rs.fields[2] >> s->EventId;
+ rs.fields[2] >> s->EventUid;
rs.fields[3] >> s->Title;
rs.fields[4] >> s->Search;
rs.fields[5] >> s->Priority;