summaryrefslogtreecommitdiff
path: root/p2pvr/lib/recorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'p2pvr/lib/recorder.cpp')
-rw-r--r--p2pvr/lib/recorder.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/p2pvr/lib/recorder.cpp b/p2pvr/lib/recorder.cpp
new file mode 100644
index 0000000..89902a9
--- /dev/null
+++ b/p2pvr/lib/recorder.cpp
@@ -0,0 +1,99 @@
+#include "recorder.h"
+#include "bindTimerTask.h"
+#include <boost/bind.hpp>
+#include <logger.h>
+#include <commonHelpers.h>
+#include <scopeObject.h>
+#include "serviceStreamer.h"
+#include "storage.h"
+#include "muxer.h"
+
+std::string Recorder::extension;
+std::string Recorder::muxerCommand;
+
+DECLARE_OPTIONS(Recorder, "P2PVR Recorder options")
+("p2pvr.recorder.extension", Options::value(&extension, "avi"),
+ "File extension to save with (default: avi)")
+("p2pvr.recorder.muxercommand", Options::value(&muxerCommand, "/usr/bin/ffmpeg -f mpegts -i - -f avi -codec copy -"),
+ "File extension to save with (default: '/usr/bin/ffmpeg -f mpegts -i - -f avi -codec copy -')")
+END_OPTIONS(Recorder);
+
+Recorder::Recorder(Ice::ObjectAdapterPtr a, IceUtil::TimerPtr t) :
+ adapter(a),
+ timer(t)
+{
+ Logger()->message(LOG_DEBUG, __PRETTY_FUNCTION__);
+ RefreshSchedules(Ice::Current());
+}
+
+void
+Recorder::RefreshSchedules(const Ice::Current &)
+{
+ std::lock_guard<std::mutex> g(lock);
+ BOOST_FOREACH(auto & t, pendingRecordings) {
+ timer->cancel(t);
+ }
+ pendingRecordings.clear();
+ auto schedules = P2PVR::SchedulesPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Schedules")));
+ 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;;
+ }) != currentRecordings.end()) {
+ continue;
+ }
+ auto schedule = schedules->GetSchedule(s->ScheduleId);
+ auto service = si->GetService(s->ServiceId);
+ auto event = si->GetEvent(s->ServiceId, s->EventId);
+
+ auto startIn = std::max<time_t>(event->StartTime - schedule->Early - time(NULL), 0);
+ IceUtil::TimerTaskPtr startTimer = new BindTimerTask(boost::bind(&Recorder::StartRecording, this, schedule, service, event));
+ timer->schedule(startTimer, IceUtil::Time::seconds(startIn));
+ pendingRecordings.push_back(startTimer);
+ Logger()->messagebf(LOG_DEBUG, "Recording %s scheduled for %s seconds", event->Title, startIn);
+ }
+}
+
+void
+Recorder::StartRecording(P2PVR::SchedulePtr schedule, DVBSI::ServicePtr service, DVBSI::EventPtr event)
+{
+ std::lock_guard<std::mutex> g(lock);
+ auto storage = P2PVR::StoragePrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Storage")));
+ auto recordings = P2PVR::RecordingsPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Recordings")));
+
+ auto id = storage->CreateForEventRecording(extension, schedule, service, event);
+ auto store = storage->OpenForWrite(id);
+ ScopeObject _store(NULL, NULL, [this,&store,&storage,&id]() { storage->Close(store); storage->Delete(id); });
+ auto muxer = P2PVR::RawDataClientPrx::checkedCast(adapter->addWithUUID(new Muxer(store, muxerCommand)));
+ ScopeObject _muxer(NULL, NULL, [this,&muxer]() { adapter->remove(muxer->ice_getIdentity()); });
+ auto ss = ServiceStreamerPtr(new ServiceStreamer(service->ServiceId, muxer, adapter->getCommunicator(), adapter));
+
+ ss->Start();
+ Logger()->messagebf(LOG_INFO, "Started recording %s (%s - %s) on %s (%d)",
+ 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));
+ auto newCurrent = CurrentPtr(new Current({muxer, store, ss, schedule, service, event, IceUtil::TimerTaskPtr()}));
+ currentRecordings.insert(newCurrent);
+
+ auto stopIn = event->StopTime + schedule->Late - time(NULL);
+ newCurrent->stopTimer = new BindTimerTask(boost::bind(&Recorder::StopRecording, this, newCurrent));
+ timer->schedule(newCurrent->stopTimer, IceUtil::Time::seconds(stopIn));
+ Logger()->messagebf(LOG_DEBUG, "Recording %s scheduled stop in %s seconds", event->Title, stopIn);
+}
+
+void
+Recorder::StopRecording(CurrentPtr c)
+{
+ std::lock_guard<std::mutex> g(lock);
+ Logger()->messagebf(LOG_DEBUG, "Stopping %s", c->event->Title);
+ c->stream->Stop();
+ adapter->remove(c->muxer->ice_getIdentity());
+ currentRecordings.erase(c);
+ auto storage = P2PVR::StoragePrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Storage")));
+ storage->Close(c->store);
+ Logger()->messagebf(LOG_DEBUG, "Stopped %s", c->event->Title);
+}
+