diff options
Diffstat (limited to 'p2pvr/lib/recorder.cpp')
-rw-r--r-- | p2pvr/lib/recorder.cpp | 99 |
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); +} + |