diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-08-06 13:34:44 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-08-06 13:34:44 +0100 |
commit | 661856d0e138e5f1bc6809341b66e69eff903b1b (patch) | |
tree | 7fbf3491052ad94ed64fd49f9a14f19a9928cb54 | |
parent | Drop out local file hanlde for AdHoc's (diff) | |
download | p2pvr-661856d0e138e5f1bc6809341b66e69eff903b1b.tar.bz2 p2pvr-661856d0e138e5f1bc6809341b66e69eff903b1b.tar.xz p2pvr-661856d0e138e5f1bc6809341b66e69eff903b1b.zip |
Unify local/global devices and tuners into a single coherent service
39 files changed, 636 insertions, 688 deletions
diff --git a/p2pvr/carddaemon/carddaemon.cpp b/p2pvr/carddaemon/carddaemon.cpp index f7889e8..c20ca4e 100644 --- a/p2pvr/carddaemon/carddaemon.cpp +++ b/p2pvr/carddaemon/carddaemon.cpp @@ -1,5 +1,5 @@ #include <icetrayService.h> -#include "localDevices.h" +#include "devices.h" #include <Ice/ObjectAdapter.h> #include <Ice/Communicator.h> #include <IceUtil/Timer.h> @@ -9,8 +9,7 @@ class CardDaemon : public IceTray::Service { public: void addObjects(const std::string &, const Ice::CommunicatorPtr & ic, const Ice::StringSeq &, const Ice::ObjectAdapterPtr & adapter) override { - IceUtil::TimerPtr timer = new IceUtil::Timer(); - adapter->add(new LocalDevicesI(adapter, timer), ic->stringToIdentity("Devices")); + adapter->add(new DevicesI(), ic->stringToIdentity("Devices")); } }; diff --git a/p2pvr/daemon/daemon.cpp b/p2pvr/daemon/daemon.cpp index c19f5cf..3a3b40f 100644 --- a/p2pvr/daemon/daemon.cpp +++ b/p2pvr/daemon/daemon.cpp @@ -1,5 +1,4 @@ -#include "localDevices.h" -#include "globalDevices.h" +#include "devices.h" #include "maintenance.h" #include "si.h" #include "schedules.h" @@ -37,8 +36,7 @@ class P2PvrDaemon : public IceTray::Service { IceUtil::TimerPtr timer = new IceUtil::Timer(); auto db = getConnectionPool(ic, "postgresql", "postgres"); - auto localDevices = add<LocalDevices>(ic, adapter, new LocalDevicesI(adapter, timer), "Devices"); - auto globalDevices = add<Devices>(ic, adapter, new GlobalDevices(), "GlobalDevices"); + auto devices = add<Tuners>(ic, adapter, new DevicesI(), "Devices"); auto maintenance = add<Maintenance>(ic, adapter, new MaintenanceI(db, adapter, timer), "Maintenance"); auto si = add<SI>(ic, adapter, new SII(db), "SI"); auto schedules = add<Schedules>(ic, adapter, new SchedulesI(db), "Schedules"); diff --git a/p2pvr/daemon/globalDevices.cpp b/p2pvr/daemon/globalDevices.cpp deleted file mode 100644 index 0705415..0000000 --- a/p2pvr/daemon/globalDevices.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "globalDevices.h" -#include <Ice/Ice.h> - -namespace po = boost::program_options; - -namespace P2PVR { -GlobalDevices::Options::Options() : - IceTray::Options("P2PVR Devices") -{ -} - -ICETRAY_OPTIONS(GlobalDevices::Options, - ("p2pvr.globaldevices.carddaemon", po::value(&Devices), - "ICE address of remote device pools (<object>:<endpoint>)") -) - -TunerPrx -GlobalDevices::GetTunerSpecific(const DVBSI::DeliveryPtr & delivery, const Ice::Current & ice) -{ - auto ic = ice.adapter->getCommunicator(); - for (const auto & pool : options->Devices) { - try { - auto poolprx = DevicesPrx::checkedCast(ic->stringToProxy(pool)); - return poolprx->GetTunerSpecific(delivery); - } - catch (...) { - } - } - throw NoSuitableDeviceAvailable(); -} - -TunerPrx -GlobalDevices::GetTunerAny(const DVBSI::DeliveryPtr & delivery, const Ice::Current & ice) -{ - auto ic = ice.adapter->getCommunicator(); - for (const auto & pool : options->Devices) { - try { - auto poolprx = DevicesPrx::checkedCast(ic->stringToProxy(pool)); - return poolprx->GetTunerAny(delivery); - } - catch (...) { - } - } - throw NoSuitableDeviceAvailable(); -} - -PrivateTunerPrx -GlobalDevices::GetPrivateTuner(short type, const Ice::Current & ice) -{ - auto ic = ice.adapter->getCommunicator(); - for (const auto & pool : options->Devices) { - try { - auto poolprx = DevicesPrx::checkedCast(ic->stringToProxy(pool)); - return poolprx->GetPrivateTuner(type); - } - catch (...) { - } - } - throw NoSuitableDeviceAvailable(); -} - -void -GlobalDevices::ReleaseTuner(const TunerPrx & tuner, const Ice::Current & ice) -{ - auto ic = ice.adapter->getCommunicator(); - for (const auto & pool : options->Devices) { - auto poolprx = DevicesPrx::checkedCast(ic->stringToProxy(pool)); - poolprx->ReleaseTuner(tuner); - } -} - -int -GlobalDevices::TunerCount(const Ice::Current & ice) -{ - int total = 0; - auto ic = ice.adapter->getCommunicator(); - for (const auto & pool : options->Devices) { - try { - auto poolprx = DevicesPrx::checkedCast(ic->stringToProxy(pool)); - total += poolprx->TunerCount(); - } - catch (...) { - // Not available, don't count 'em - } - } - return total; -} -} - diff --git a/p2pvr/daemon/globalDevices.h b/p2pvr/daemon/globalDevices.h deleted file mode 100644 index 43a7dc3..0000000 --- a/p2pvr/daemon/globalDevices.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GLOBALDEVICES_H -#define GLOBALDEVICES_H - -// Global devices implements a device collection (Devices) for any devices known -// throughout the system through other Devices interfaces - -#include <dvb.h> -#include <options.h> - -namespace P2PVR { -class GlobalDevices : public Devices { - public: - class Options : public IceTray::Options { - public: - Options(); - - ICETRAY_OPTIONS_DECLARE; - - std::vector<std::string> Devices; - }; - - TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr &, const Ice::Current &); - TunerPrx GetTunerAny(const DVBSI::DeliveryPtr &, const Ice::Current &); - PrivateTunerPrx GetPrivateTuner(short type, const Ice::Current &); - void ReleaseTuner(const TunerPrx &, const Ice::Current &); - int TunerCount(const Ice::Current &); - - private: - IceTray::OptionsResolver<Options> options; -}; -} - -#endif - - diff --git a/p2pvr/daemon/maintenance/events.cpp b/p2pvr/daemon/maintenance/events.cpp index 05c9149..2dd91af 100644 --- a/p2pvr/daemon/maintenance/events.cpp +++ b/p2pvr/daemon/maintenance/events.cpp @@ -43,7 +43,7 @@ class SiEventsStream : public Slicer::Stream<::DVBSI::EventPtr> { void Produce(const Consumer & ch) override { auto ic = ice.adapter->getCommunicator(); - auto devs = DevicesPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("GlobalDevices"))); + auto devs = TunersPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("Devices"))); auto si = SIPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("SI"))); if (!devs || !si) { throw std::runtime_error("bad proxy(s)"); @@ -54,12 +54,10 @@ class SiEventsStream : public Slicer::Stream<::DVBSI::EventPtr> { throw std::runtime_error("no delivery methods"); } logger->messagebf(LOG::DEBUG, "%s: Getting a tuner", __PRETTY_FUNCTION__); - auto tuner = devs->GetTunerAny(delivery); logger->messagebf(LOG::DEBUG, "%s: Fetching events", __PRETTY_FUNCTION__); TemporaryIceAdapterObject<RawDataClient> parser(ice.adapter, new SiEventsHandler(ch, logger)); - tuner->SendEventInformation(parser); - devs->ReleaseTuner(tuner); + devs->SendEventInformation(delivery, parser); } private: diff --git a/p2pvr/daemon/maintenance/network.cpp b/p2pvr/daemon/maintenance/network.cpp index 3e08628..c514175 100644 --- a/p2pvr/daemon/maintenance/network.cpp +++ b/p2pvr/daemon/maintenance/network.cpp @@ -72,11 +72,11 @@ class SiNetworkInformationMerger : public DVBSI::SiNetworkInformationParser { }; void -MaintenanceI::UpdateNetwork(short type, const Ice::Current & ice) +MaintenanceI::UpdateNetwork(short, const Ice::Current & ice) { auto dbc = db->get(); auto ic = ice.adapter->getCommunicator(); - auto devs = DevicesPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("GlobalDevices"))); + auto devs = TunersPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("Devices"))); auto si = SIPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("SI"))); auto siparser = new SiNetworkInformationMerger(dbc.get(), logger); TemporaryIceAdapterObject<RawDataClient> parser(ice.adapter, siparser); @@ -89,32 +89,11 @@ MaintenanceI::UpdateNetwork(short type, const Ice::Current & ice) auto transport = si->GetDeliveryForSi(); if (transport) { - TunerPrx tuner; - try { - tuner = devs->GetTunerAny(transport); - tuner->SendNetworkInformation(parser); - devs->ReleaseTuner(tuner); - return; - } - catch (const NoSuitableDeviceAvailable &) { - logger->messagebf(LOG::WARNING, "%s: Failed to get a suitable tuner", __PRETTY_FUNCTION__); - throw; - } - catch (const std::exception & ex) { - logger->messagebf(LOG::WARNING, "%s: Failed to fetch network information: %s", __PRETTY_FUNCTION__, ex.what()); - devs->ReleaseTuner(tuner); - throw; - } - catch (...) { - logger->messagebf(LOG::WARNING, "%s: Failed to fetch network information", __PRETTY_FUNCTION__); - devs->ReleaseTuner(tuner); - throw; - } + devs->SendNetworkInformation(transport, parser); + return; } // If we can't do that, do a complete scan - auto tuner = devs->GetPrivateTuner(type); - tuner->ScanAndSendNetworkInformation(parser); - devs->ReleaseTuner(tuner); + devs->ScanAndSendNetworkInformation(parser); } } diff --git a/p2pvr/daemon/maintenance/services.cpp b/p2pvr/daemon/maintenance/services.cpp index d83e68a..12b23ce 100644 --- a/p2pvr/daemon/maintenance/services.cpp +++ b/p2pvr/daemon/maintenance/services.cpp @@ -43,7 +43,7 @@ void MaintenanceI::UpdateServices(const Ice::Current & ice) { auto ic = ice.adapter->getCommunicator(); - auto devs = DevicesPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("GlobalDevices"))); + auto devs = TunersPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("Devices"))); auto si = SIPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("SI"))); if (!devs || !si) { @@ -60,12 +60,9 @@ MaintenanceI::UpdateServices(const Ice::Current & ice) } DB::TransactionScope tx(dbc.get()); - logger->messagebf(LOG::DEBUG, "%s: Getting a tuner", __PRETTY_FUNCTION__); - auto tuner = devs->GetTunerAny(delivery); logger->messagebf(LOG::DEBUG, "%s: Fetching service list", __PRETTY_FUNCTION__); - tuner->SendServiceDescriptions(parser); + devs->SendServiceDescriptions(delivery, parser); logger->messagebf(LOG::INFO, "%s: Updated service list", __PRETTY_FUNCTION__); - devs->ReleaseTuner(tuner); } } diff --git a/p2pvr/daemon/recorder.cpp b/p2pvr/daemon/recorder.cpp index c797d04..f32eb73 100644 --- a/p2pvr/daemon/recorder.cpp +++ b/p2pvr/daemon/recorder.cpp @@ -56,7 +56,7 @@ RecorderI::StartRecording(SchedulePtr schedule, ::DVBSI::ServicePtr service, Eve std::lock_guard<std::mutex> g(lock); auto storage = StoragePrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Storage"))); auto recordings = RecordingsPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Recordings"))); - auto devices = DevicesPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("GlobalDevices"))); + auto devices = TunersPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("Devices"))); auto si = SIPrx::checkedCast(adapter->createProxy(adapter->getCommunicator()->stringToIdentity("SI"))); auto recordingId = recordings->NewRecording(new Recording(0, schedule->ScheduleId, event->EventUid)); diff --git a/p2pvr/daemon/schedules.cpp b/p2pvr/daemon/schedules.cpp index 4fd2054..d948603 100644 --- a/p2pvr/daemon/schedules.cpp +++ b/p2pvr/daemon/schedules.cpp @@ -194,7 +194,7 @@ void SchedulesI::DoReschedule(const Ice::Current & ice) { auto ic = ice.adapter->getCommunicator(); - auto devs = P2PVR::DevicesPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("GlobalDevices"))); + auto devs = P2PVR::TunersPrx::checkedCast(ice.adapter->createProxy(ic->stringToIdentity("Devices"))); unsigned int tunerCount = devs->TunerCount(); // Load list from database diff --git a/p2pvr/daemon/unittests/mockDefs.cpp b/p2pvr/daemon/unittests/mockDefs.cpp index 0bba8c0..8282492 100644 --- a/p2pvr/daemon/unittests/mockDefs.cpp +++ b/p2pvr/daemon/unittests/mockDefs.cpp @@ -28,8 +28,7 @@ StandardMockDatabasePlusOffset::StandardMockDatabasePlusOffset(const Ice::String } TestClient::TestClient() : - localDevices(getProxy<LocalDevicesPrx>("Devices")), - devices(getProxy<DevicesPrx>("GlobalDevices")), + devices(getProxy<TunersPrx>("Devices")), maint(getProxy<MaintenancePrx>("Maintenance")), si(getProxy<SIPrx>("SI")), schedules(getProxy<SchedulesPrx>("Schedules")), diff --git a/p2pvr/daemon/unittests/mockDefs.h b/p2pvr/daemon/unittests/mockDefs.h index fa6490c..1589440 100644 --- a/p2pvr/daemon/unittests/mockDefs.h +++ b/p2pvr/daemon/unittests/mockDefs.h @@ -20,8 +20,7 @@ class DLL_PUBLIC TestClient : public IceTray::DryIceClient { public: TestClient(); - LocalDevicesPrx localDevices; - DevicesPrx devices; + TunersPrx devices; MaintenancePrx maint; SIPrx si; SchedulesPrx schedules; diff --git a/p2pvr/daemon/unittests/mockDevices.cpp b/p2pvr/daemon/unittests/mockDevices.cpp index f0ec930..3e04c85 100644 --- a/p2pvr/daemon/unittests/mockDevices.cpp +++ b/p2pvr/daemon/unittests/mockDevices.cpp @@ -3,31 +3,96 @@ #include <Ice/ObjectAdapter.h> namespace P2PVR { -namespace Testing { -TunerPrx MockDevices::GetTunerSpecific(const DVBSI::DeliveryPtr&, const Ice::Current & ice) -{ - return PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner())); -} + namespace Testing { + void MockDevices::ScanAndSendNetworkInformation(const RawDataClientPrx & target, const ::Ice::Current & ice) + { + MockTuner mt(ice.adapter->getCommunicator()); + mt.ScanAndSendNetworkInformation(target); + } -TunerPrx MockDevices::GetTunerAny(const DVBSI::DeliveryPtr&, const Ice::Current & ice) -{ - return PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner())); -} + void MockDevices::SendNetworkInformation(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendNetworkInformation(target); + } -PrivateTunerPrx MockDevices::GetPrivateTuner(Ice::Short, const Ice::Current & ice) -{ - return PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new MockTuner())); -} + void MockDevices::SendBouquetAssociations(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendBouquetAssociations(target); + } -void MockDevices::ReleaseTuner(const TunerPrx & tuner, const Ice::Current & ice) -{ - ice.adapter->remove(tuner->ice_getIdentity()); -} + void MockDevices::SendServiceDescriptions(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendServiceDescriptions(target); + } -Ice::Int MockDevices::TunerCount(const Ice::Current&) -{ - return 1; -} -} + void MockDevices::SendProgramAssociationTable(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendProgramAssociationTable(target); + } + + void MockDevices::SendProgramMap(const ::DVBSI::DeliveryPtr & del, ::Ice::Int pid, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendProgramMap(pid, target); + } + + void MockDevices::SendEventInformation(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + MockTuner mt(ice.adapter->getCommunicator()); + mt.SendEventInformation(target); + } + + ::Ice::Int MockDevices::StartSendingTS(const ::DVBSI::DeliveryPtr & del, const PacketIds & pids, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + TunerPtr tuner = new MockTuner(ice.adapter->getCommunicator()); + return bgOps.insert({ tuner->StartSendingTS(pids, target), tuner }).first->first; + } + + ::Ice::Int MockDevices::StartSendingSection(const ::DVBSI::DeliveryPtr & del, ::Ice::Int sid, const RawDataClientPrx & target, const ::Ice::Current & ice) + { + BOOST_ASSERT(del); + TunerPtr tuner = new MockTuner(ice.adapter->getCommunicator()); + return bgOps.insert({ tuner->StartSendingSection(sid, target), tuner }).first->first; + } + + void MockDevices::StopSending(::Ice::Int handle, const ::Ice::Current &) + { + BOOST_ASSERT(handle); + auto itr = bgOps.find(handle); + BOOST_ASSERT(itr != bgOps.end()); + BOOST_ASSERT(itr->second); + itr->second->StopSending(handle); + bgOps.erase(itr); + } + + + void MockDevices::Scan(const std::string &, const Ice::Current &) + { + } + + void MockDevices::Add(const std::string &, const Ice::Current &) + { + } + + void MockDevices::Remove(const std::string &, const Ice::Current &) + { + } + + ::Ice::Int MockDevices::TunerCount(const Ice::Current &) + { + return 1; + } + } } diff --git a/p2pvr/daemon/unittests/mockDevices.h b/p2pvr/daemon/unittests/mockDevices.h index be04772..bc0a22a 100644 --- a/p2pvr/daemon/unittests/mockDevices.h +++ b/p2pvr/daemon/unittests/mockDevices.h @@ -5,16 +5,30 @@ #include <visibility.h> namespace P2PVR { -namespace Testing { -class DLL_PUBLIC MockDevices : public Devices { - public: - TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr&, const Ice::Current & ice) override; - TunerPrx GetTunerAny(const DVBSI::DeliveryPtr&, const Ice::Current & ice) override; - PrivateTunerPrx GetPrivateTuner(Ice::Short, const Ice::Current & ice) override; - void ReleaseTuner(const TunerPrx & tuner, const Ice::Current & ice) override; - Ice::Int TunerCount(const Ice::Current&) override; -}; -} + namespace Testing { + class DLL_PUBLIC MockDevices : public Tuners { + public: + virtual void ScanAndSendNetworkInformation(const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendNetworkInformation(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendBouquetAssociations(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendServiceDescriptions(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendProgramAssociationTable(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendProgramMap(const ::DVBSI::DeliveryPtr&, ::Ice::Int, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendEventInformation(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual ::Ice::Int StartSendingTS(const ::DVBSI::DeliveryPtr&, const PacketIds&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual ::Ice::Int StartSendingSection(const ::DVBSI::DeliveryPtr&, ::Ice::Int, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void StopSending(::Ice::Int, const ::Ice::Current&) override; + + void Scan(const std::string & path, const Ice::Current &) override; + void Add(const std::string & frontend, const Ice::Current &) override; + void Remove(const std::string & frontend, const Ice::Current &) override; + ::Ice::Int TunerCount(const Ice::Current &) override; + + private: + typedef std::map<::Ice::Int, TunerPtr> BackgroundOperations; + BackgroundOperations bgOps; + }; + } } #endif diff --git a/p2pvr/daemon/unittests/testErrorHandling.cpp b/p2pvr/daemon/unittests/testErrorHandling.cpp index db07293..2ec1941 100644 --- a/p2pvr/daemon/unittests/testErrorHandling.cpp +++ b/p2pvr/daemon/unittests/testErrorHandling.cpp @@ -26,7 +26,7 @@ class Core : public StandardMockDatabase { public: Core() { - replace("GlobalDevices", new MockDevices()); + replace("Devices", new MockDevices()); } }; @@ -72,40 +72,36 @@ BOOST_AUTO_TEST_CASE(TestRawDataClient) { BOOST_TEST_CHECKPOINT("Setup"); auto del = si->GetDeliveryForSi(); - auto gd = devices->GetTunerAny(del); TemporaryIceAdapterObject<RawDataClient> a(getAdapter(), new TestDataClient()); BOOST_TEST_CHECKPOINT("Make successful call"); - gd->SendNetworkInformation(a); + devices->SendNetworkInformation(del, a); } BOOST_AUTO_TEST_CASE(TestParser) { BOOST_TEST_CHECKPOINT("Setup"); auto del = si->GetDeliveryForSi(); - auto gd = devices->GetTunerAny(del); TemporaryIceAdapterObject<RawDataClient> a(getAdapter(), new TestNetworkParser()); BOOST_TEST_CHECKPOINT("Make successful call"); - gd->SendNetworkInformation(a); + devices->SendNetworkInformation(del, a); } BOOST_AUTO_TEST_CASE(TestRawDataClientWithError) { BOOST_TEST_CHECKPOINT("Setup"); auto del = si->GetDeliveryForSi(); - auto gd = devices->GetTunerAny(del); TemporaryIceAdapterObject<RawDataClient> a(getAdapter(), new FailingTestClient()); BOOST_TEST_CHECKPOINT("Make failing call"); - BOOST_REQUIRE_THROW(gd->SendNetworkInformation(a), DataHandlingException); + BOOST_REQUIRE_THROW(devices->SendNetworkInformation(del, a), DataHandlingException); } BOOST_AUTO_TEST_CASE(TestParserWithError) { BOOST_TEST_CHECKPOINT("Setup"); auto del = si->GetDeliveryForSi(); - auto gd = devices->GetTunerAny(del); TemporaryIceAdapterObject<RawDataClient> a(getAdapter(), new FailingTestNetworkParser()); BOOST_TEST_CHECKPOINT("Make failing call"); - BOOST_REQUIRE_THROW(gd->SendNetworkInformation(a), DataHandlingException); + BOOST_REQUIRE_THROW(devices->SendNetworkInformation(del, a), DataHandlingException); } BOOST_AUTO_TEST_SUITE_END() diff --git a/p2pvr/daemon/unittests/testMaint.cpp b/p2pvr/daemon/unittests/testMaint.cpp index 026ec27..a1fc6fd 100644 --- a/p2pvr/daemon/unittests/testMaint.cpp +++ b/p2pvr/daemon/unittests/testMaint.cpp @@ -27,7 +27,7 @@ class TestService : public SchemaOnlyMockDatabase { public: TestService() { - replace("GlobalDevices", new MockDevices()); + replace("Devices", new MockDevices()); replace("Schedules", new MockScheduler()); } }; diff --git a/p2pvr/daemon/unittests/testRecording.cpp b/p2pvr/daemon/unittests/testRecording.cpp index e4dc6c1..fe81b7d 100644 --- a/p2pvr/daemon/unittests/testRecording.cpp +++ b/p2pvr/daemon/unittests/testRecording.cpp @@ -28,7 +28,7 @@ class TestService : public StandardMockDatabase { public: TestService() { - replace("GlobalDevices", new MockDevices()); + replace("Devices", new MockDevices()); replace("Schedules", new MockScheduler()); } }; diff --git a/p2pvr/daemon/unittests/testSched.cpp b/p2pvr/daemon/unittests/testSched.cpp index badf35c..9f6881a 100644 --- a/p2pvr/daemon/unittests/testSched.cpp +++ b/p2pvr/daemon/unittests/testSched.cpp @@ -26,7 +26,7 @@ class TestService : public StandardMockDatabasePlusOffset { public: TestService() { - replace("GlobalDevices", new MockDevices()); + replace("Devices", new MockDevices()); replace("Recorder", new MockRecorder()); } }; diff --git a/p2pvr/devices/devices.cpp b/p2pvr/devices/devices.cpp new file mode 100644 index 0000000..541cfa5 --- /dev/null +++ b/p2pvr/devices/devices.cpp @@ -0,0 +1,258 @@ +#include "devices.h" +#include <Ice/Ice.h> +#include "tuner.h" +#include "bindTimerTask.h" +#include <lockHelpers.h> + +namespace P2PVR { +template<typename T> +T * +get_pointer(const IceInternal::Handle<T> & t) BOOST_NOEXCEPT +{ + return t.get(); +} + +class DLL_PRIVATE OpenTuner { + public: + OpenTuner(DVBSI::DeliveryPtr, TunerPtr); + + const DVBSI::DeliveryPtr delivery; + const TunerPtr tuner; + + unsigned int clients; +}; + +DevicesI::Options::Options() : + IceTray::Options("P2PVR Devices") +{ +} + +ICETRAY_OPTIONS(DevicesI::Options, + ("p2pvr.localdevices.frontend", boost::program_options::value(&devices), "Frontend of DVB device(s) to use (/dev/dvb/adapterX/frontendY)") +); + +IceTray::Logging::LoggerPtr DevicesI::logger(LOGMANAGER()->getLogger<DevicesI>()); + +DevicesI::DevicesI() +{ + devices = options->devices; + logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); +} + +DevicesI::~DevicesI() +{ + logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); +} + +TunerPtr +DevicesI::getTuner() +{ + if (devices.empty()) { + throw NoSuitableDeviceAvailable(); + } + for (auto devItr = devices.begin(); devItr != devices.end(); devItr++) { + try { + return new DVB::TunerI(*devItr); + } + catch (...) { + logger->messagebf(LOG::DEBUG, "%s: Failed to open device %s", __PRETTY_FUNCTION__, + *devItr); + } + } + throw NoSuitableDeviceAvailable(); +} + +TunerPtr +DevicesI::getTuner(const DVBSI::DeliveryPtr & delivery) +{ + logger->messagebf(LOG::DEBUG, "%s: Searching for an open sharable tuner (frequency %d)", __PRETTY_FUNCTION__, delivery->Frequency); + Lock(lock); + // Check for an already open tuner which is correctly tuned. + auto existingItr = openDevices.find(delivery->TransportStreamId); + if (existingItr != openDevices.end()) { + existingItr->second->clients += 1; + return existingItr->second->tuner; + } + // Open a tuner and tune it as required. + if (devices.empty()) { + throw NoSuitableDeviceAvailable(); + } + for (auto devItr = devices.begin(); devItr != devices.end(); devItr++) { + try { + TunerPtr tuner = new DVB::TunerI(*devItr); + tuner->TuneTo(delivery); + openDevices.insert({ delivery->TransportStreamId, OpenTunerPtr(new OpenTuner(delivery, tuner)) }); + devices.erase(devItr); + return tuner; + } + catch (...) { + logger->messagebf(LOG::DEBUG, "%s: Failed to open and tune device %s to frequency %d", __PRETTY_FUNCTION__, + *devItr, delivery->Frequency); + } + } + logger->messagebf(LOG::DEBUG, "%s: Failed to open and tune any device to frequency %d", __PRETTY_FUNCTION__, + delivery->Frequency); + throw NoSuitableDeviceAvailable(); +} + +TunerPtr +DevicesI::getTuner(const DeliveryProvider & provider) +{ + ScopeLock(lock) { + if (!openDevices.empty()) { + auto openDevice = openDevices.begin()->second; + openDevice->clients++; + return openDevice->tuner; + } + + } + return getTuner(provider()); +} + +void +DevicesI::releaseTuner(const TunerPtr & tuner) +{ + Lock(lock); + logger->messagebf(LOG::DEBUG, "%s", __PRETTY_FUNCTION__); + auto openTuner = std::find_if(openDevices.begin(), openDevices.end(), [&tuner](const auto & ot) { + return ot.second->tuner == tuner; + }); + if (openTuner == openDevices.end()) { + logger->messagebf(LOG::DEBUG, "%s: Not one of mine", __PRETTY_FUNCTION__); + throw DeviceError(); + } + logger->messagebf(LOG::DEBUG, "%s: Locally owned deivce %s", __PRETTY_FUNCTION__, openTuner->first); + openTuner->second->clients -= 1; + if (openTuner->second->clients == 0) { + openDevices.erase(openTuner); + devices.push_back(openTuner->second->tuner->GetDevice()); + } +} + +void +DevicesI::Scan(const std::string &, const Ice::Current &) +{ + Lock(lock); +} + +void +DevicesI::Add(const std::string & frontend, const Ice::Current &) +{ + Lock(lock); + devices.push_back(frontend); +} + +void +DevicesI::Remove(const std::string & frontend, const Ice::Current &) +{ + Lock(lock); + devices.erase(std::remove(devices.begin(), devices.end(), frontend), devices.end()); +} + +::Ice::Int +DevicesI::TunerCount(const Ice::Current &) +{ + Lock(lock); + return devices.size() + openDevices.size(); +} + +OpenTuner::OpenTuner(DVBSI::DeliveryPtr d, TunerPtr t) : + delivery(d), + tuner(t), + clients(1) +{ +} + +void +DevicesI::finiteTunerOperation(TunerPtr && tuner, const Target & target) +{ + try { + target(tuner); + releaseTuner(tuner); + } + catch (...) { + releaseTuner(tuner); + throw; + } +} + +void +DevicesI::ScanAndSendNetworkInformation(const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(), boost::bind(&Tuner::ScanAndSendNetworkInformation, _1, target)); +} + +void +DevicesI::SendNetworkInformation(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendNetworkInformation, _1, target)); +} + +void +DevicesI::SendBouquetAssociations(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current &) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendBouquetAssociations, _1, target)); +} + +void +DevicesI::SendServiceDescriptions(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendServiceDescriptions, _1, target)); +} + +void +DevicesI::SendProgramAssociationTable(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendProgramAssociationTable, _1, target)); +} + +void +DevicesI::SendProgramMap(const ::DVBSI::DeliveryPtr & del, ::Ice::Int pids, const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendProgramMap, _1, pids, target)); +} + +void +DevicesI::SendEventInformation(const ::DVBSI::DeliveryPtr & del, const RawDataClientPrx & target, const ::Ice::Current&) +{ + finiteTunerOperation(getTuner(del), boost::bind(&Tuner::SendEventInformation, _1, target)); +} + +::Ice::Int +DevicesI::StartSendingTS(const ::DVBSI::DeliveryPtr & del, const PacketIds & pids, const RawDataClientPrx & target, const ::Ice::Current&) +{ + auto tuner = getTuner(del); + try { + return backgroundOperations.insert({ tuner->StartSendingTS(pids, target), tuner }).first->first; + } + catch (...) { + releaseTuner(tuner); + throw; + } +} + +::Ice::Int +DevicesI::StartSendingSection(const ::DVBSI::DeliveryPtr & del, ::Ice::Int sid, const RawDataClientPrx & target, const ::Ice::Current&) +{ + auto tuner = getTuner(del); + try { + return backgroundOperations.insert({ tuner->StartSendingSection(sid, target), tuner }).first->first; + } + catch (...) { + releaseTuner(tuner); + throw; + } +} + +void +DevicesI::StopSending(::Ice::Int handle, const ::Ice::Current&) +{ + auto tunerItr = backgroundOperations.find(handle); + if (tunerItr != backgroundOperations.end()) { + tunerItr->second->StopSending(handle); + backgroundOperations.erase(handle); + } +} + +} + diff --git a/p2pvr/devices/devices.h b/p2pvr/devices/devices.h new file mode 100644 index 0000000..0d8af11 --- /dev/null +++ b/p2pvr/devices/devices.h @@ -0,0 +1,69 @@ +#ifndef LOCALDEVICES_H +#define LOCALDEVICES_H + +// Local devices implements a device collection (Devices) for any devices physically +// attached to the local machine; that is, can be accessed directly through /dev/dvb/adapterX + +#include <dvb.h> +#include <options.h> +#include <mutex> +#include <visibility.h> +#include <logger.h> +#include <boost/filesystem/path.hpp> + +namespace P2PVR { +class OpenTuner; +class DLL_PUBLIC DevicesI : public Tuners { + public: + class Options : public IceTray::Options { + public: + Options(); + + ICETRAY_OPTIONS_DECLARE; + + std::vector<boost::filesystem::path> devices; + }; + + DevicesI(); + ~DevicesI(); + + virtual void ScanAndSendNetworkInformation(const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendNetworkInformation(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendBouquetAssociations(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendServiceDescriptions(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendProgramAssociationTable(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendProgramMap(const ::DVBSI::DeliveryPtr&, ::Ice::Int, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void SendEventInformation(const ::DVBSI::DeliveryPtr&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual ::Ice::Int StartSendingTS(const ::DVBSI::DeliveryPtr&, const PacketIds&, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual ::Ice::Int StartSendingSection(const ::DVBSI::DeliveryPtr&, ::Ice::Int, const RawDataClientPrx&, const ::Ice::Current&) override; + virtual void StopSending(::Ice::Int, const ::Ice::Current&) override; + + void Scan(const std::string & path, const Ice::Current &) override; + void Add(const std::string & frontend, const Ice::Current &) override; + void Remove(const std::string & frontend, const Ice::Current &) override; + ::Ice::Int TunerCount(const Ice::Current &) override; + + private: + typedef boost::function<DVBSI::DeliveryPtr()> DeliveryProvider; + TunerPtr getTuner(); + TunerPtr getTuner(const DeliveryProvider &); + TunerPtr getTuner(const DVBSI::DeliveryPtr &); + void releaseTuner(const TunerPtr &); + + typedef boost::function<void(TunerPtr)> Target; + void finiteTunerOperation(TunerPtr && tuner, const Target &); + + typedef boost::shared_ptr<OpenTuner> OpenTunerPtr; + typedef std::map<Ice::Int, OpenTunerPtr> OpenDevices; + OpenDevices openDevices; + typedef std::map<Ice::Int, TunerPtr> BackgroundOperations; + BackgroundOperations backgroundOperations; + std::vector<boost::filesystem::path> devices; + std::mutex lock; + static IceTray::Logging::LoggerPtr logger; + IceTray::OptionsResolver<Options> options; +}; +} + +#endif + diff --git a/p2pvr/devices/frontend.cpp b/p2pvr/devices/frontend.cpp index c6f258b..1026a20 100644 --- a/p2pvr/devices/frontend.cpp +++ b/p2pvr/devices/frontend.cpp @@ -6,7 +6,7 @@ namespace P2PVR { namespace DVB { -Frontend::Frontend(Tuner * t, const struct dvb_frontend_info & i, IceTray::Logging::LoggerPtr log) : +Frontend::Frontend(TunerI * t, const struct dvb_frontend_info & i, IceTray::Logging::LoggerPtr log) : tuner(t), fe_info(i), logger(log) @@ -28,8 +28,8 @@ Frontend::GetStatus() const { fe_status_t status; if (ioctl(tuner->frontendFD, FE_READ_STATUS, &status) < 0) { - logger->messagebf(LOG::ERR, "Reading frontend %s status failed (%s:%d)", tuner->Device(), strerror(errno), errno); - throw P2PVR::DeviceError(tuner->Device(), strerror(errno), errno); + logger->messagebf(LOG::ERR, "Reading frontend %s status failed (%s:%d)", tuner->GetDevice(), strerror(errno), errno); + throw P2PVR::DeviceError(tuner->GetDevice(), strerror(errno), errno); } return status; } @@ -42,5 +42,5 @@ Frontend::FactoryKey(fe_type t) } } -INSTANTIATEFACTORY(P2PVR::DVB::Frontend, P2PVR::DVB::Tuner *, const struct dvb_frontend_info &); +INSTANTIATEFACTORY(P2PVR::DVB::Frontend, P2PVR::DVB::TunerI *, const struct dvb_frontend_info &); diff --git a/p2pvr/devices/frontend.h b/p2pvr/devices/frontend.h index 4e47c10..63b000d 100644 --- a/p2pvr/devices/frontend.h +++ b/p2pvr/devices/frontend.h @@ -8,12 +8,12 @@ namespace P2PVR { namespace DVB { -class Tuner; +class TunerI; class Frontend { public: typedef boost::function<bool(long)> OnFrequencyFound; - Frontend(Tuner *, const struct dvb_frontend_info &, IceTray::Logging::LoggerPtr); + Frontend(TunerI *, const struct dvb_frontend_info &, IceTray::Logging::LoggerPtr); virtual ~Frontend(); fe_status_t GetStatus() const; @@ -25,12 +25,12 @@ class Frontend { static std::string FactoryKey(fe_type); protected: - const Tuner * tuner; + TunerI * const tuner; const struct dvb_frontend_info fe_info; IceTray::Logging::LoggerPtr logger; }; -typedef AdHoc::Factory<Frontend, Tuner *, const struct dvb_frontend_info &> FrontendFactory; +typedef AdHoc::Factory<Frontend, TunerI *, const struct dvb_frontend_info &> FrontendFactory; typedef boost::shared_ptr<Frontend> FrontendPtr; } } diff --git a/p2pvr/devices/frontends/ofdm.cpp b/p2pvr/devices/frontends/ofdm.cpp index 991996d..e6c3979 100644 --- a/p2pvr/devices/frontends/ofdm.cpp +++ b/p2pvr/devices/frontends/ofdm.cpp @@ -11,7 +11,7 @@ namespace DVB { namespace Frontends { class OFDM : public Frontend { public: - OFDM(Tuner * t, const struct dvb_frontend_info & i) : + OFDM(TunerI * t, const struct dvb_frontend_info & i) : Frontend(t, i, LOGMANAGER()->getLogger<OFDM>()) { } @@ -42,8 +42,8 @@ class OFDM : public Frontend { dvb_frontend_parameters feparams; memset(&feparams, 0, sizeof(dvb_frontend_parameters)); if (ioctl(tuner->frontendFD, FE_GET_FRONTEND, &feparams) < 0) { - logger->messagebf(LOG::ERR, "Reading frontend parameters failed (%s:%d)", tuner->Device(), strerror(errno), errno); - throw P2PVR::DeviceError(tuner->Device(), strerror(errno), errno); + logger->messagebf(LOG::ERR, "Reading frontend parameters failed (%s:%d)", tuner->GetDevice(), strerror(errno), errno); + throw P2PVR::DeviceError(tuner->GetDevice(), strerror(errno), errno); } return feparams; } @@ -57,24 +57,24 @@ class OFDM : public Frontend { } // Was it useful? if (!(status & (FE_HAS_SIGNAL | FE_HAS_CARRIER))) { - logger->messagebf(LOG::ERR, "Tuning of device %s failed (No signal or carrier: 0x%02x)", tuner->Device(), status); - throw P2PVR::DeviceError(tuner->Device(), "No carrier", 0); + logger->messagebf(LOG::ERR, "Tuning of device %s failed (No signal or carrier: 0x%02x)", tuner->GetDevice(), status); + throw P2PVR::DeviceError(tuner->GetDevice(), "No carrier", 0); } // Wait for lock for (int x = tuner->options->LockTimeout / 10; x > 0 && ((status = GetStatus()) & FE_HAS_LOCK) == 0; x -= 1) { usleep(10000); } if (!(status & FE_HAS_LOCK)) { - logger->messagebf(LOG::ERR, "Tuning of device %s failed (%s)", tuner->Device(), "No lock"); - throw P2PVR::DeviceError(tuner->Device(), "No lock", 0); + logger->messagebf(LOG::ERR, "Tuning of device %s failed (%s)", tuner->GetDevice(), "No lock"); + throw P2PVR::DeviceError(tuner->GetDevice(), "No lock", 0); } } void SetParameters(const dvb_frontend_parameters & feparams) const { if (ioctl(tuner->frontendFD, FE_SET_FRONTEND, &feparams) < 0) { - logger->messagebf(LOG::ERR, "Tuning of device %s failed (%s:%d)", tuner->Device(), strerror(errno), errno); - throw P2PVR::DeviceError(tuner->Device(), strerror(errno), errno); + logger->messagebf(LOG::ERR, "Tuning of device %s failed (%s:%d)", tuner->GetDevice(), strerror(errno), errno); + throw P2PVR::DeviceError(tuner->GetDevice(), strerror(errno), errno); } } diff --git a/p2pvr/devices/localDevices.cpp b/p2pvr/devices/localDevices.cpp deleted file mode 100644 index ac13a29..0000000 --- a/p2pvr/devices/localDevices.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "localDevices.h" -#include <Ice/Ice.h> -#include "tuner.h" -#include "bindTimerTask.h" - -namespace P2PVR { -LocalDevicesI::Devices LocalDevicesI::devices; -std::mutex LocalDevicesI::lock; - -LocalDevicesI::Options::Options() : - IceTray::Options("P2PVR Devices") -{ -} - -ICETRAY_OPTIONS(LocalDevicesI::Options, - ("p2pvr.localdevices.frontend", boost::program_options::value(&devices), "Frontend of DVB device(s) to use (/dev/dvb/adapterX/frontendY)") -); - -IceTray::Logging::LoggerPtr LocalDevicesI::logger(LOGMANAGER()->getLogger<LocalDevicesI>()); - -LocalDevicesI::LocalDevicesI(Ice::ObjectAdapterPtr adapter, IceUtil::TimerPtr t) : - timer(t), - clientCheck(new BindTimerTask(boost::bind(&LocalDevicesI::ClientCheck, this, adapter))) -{ - for (auto & device : options->devices) { - devices.insert({ device, nullptr }); - } - logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); - timer->scheduleRepeated(clientCheck, IceUtil::Time::seconds(30)); -} - -LocalDevicesI::~LocalDevicesI() -{ - logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); - timer->cancel(clientCheck); -} - -void -LocalDevicesI::ClientCheck(Ice::ObjectAdapterPtr adapter) -{ - std::lock_guard<std::mutex> g(lock); - for (auto & device : devices) { - if (device.second && device.second->tuner->GetLastUsedTime() < time(NULL) - 30) { - logger->messagebf(LOG::DEBUG, "%s: Device %s no longer in use", __PRETTY_FUNCTION__, device.first); - auto id = device.second->tuner->ice_getIdentity(); - if (adapter->find(id)) { - adapter->remove(id); - } - device.second.reset(); - } - } -} - -TunerPrx -LocalDevicesI::GetTunerSpecific(const DVBSI::DeliveryPtr & delivery, const Ice::Current & ice) -{ - std::lock_guard<std::mutex> g(lock); - logger->messagebf(LOG::DEBUG, "%s: Searching for an open sharable tuner (frequency %d)", __PRETTY_FUNCTION__, delivery->Frequency); - auto openTuner = std::find_if(devices.begin(), devices.end(), [delivery](const Devices::value_type & ot) { - return ot.second && !ot.second->openedPrivate && ot.second->delivery && ot.second->delivery->Frequency == delivery->Frequency; - }); - if (openTuner != devices.end()) { - openTuner->second->clients += 1; - return openTuner->second->tuner; - } - - openTuner = std::find_if(devices.begin(), devices.end(), [](const Devices::value_type & ot) { return !ot.second; }); - if (openTuner == devices.end()) { - logger->messagebf(LOG::DEBUG, "%s: None suitable and none free (frequency %d)", - __PRETTY_FUNCTION__, delivery->Frequency); - throw NoSuitableDeviceAvailable(); - } - - logger->messagebf(LOG::DEBUG, "%s: Opening a sharable tuner (frequency %d, frontend %s)", - __PRETTY_FUNCTION__, delivery->Frequency, openTuner->first); - PrivateTunerPtr t = new DVB::Tuner(openTuner->first); - t->TuneTo(delivery, ice); - auto tuner = PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(t)); - openTuner->second = OpenTunerPtr(new OpenTuner(delivery, tuner, false)); - - logger->messagebf(LOG::DEBUG, "%s: Tuned, returning (frequency %d, frontend %s)", - __PRETTY_FUNCTION__, delivery->Frequency, openTuner->first); - return tuner; -} - -TunerPrx -LocalDevicesI::GetTunerAny(const DVBSI::DeliveryPtr & delivery, const Ice::Current & ice) -{ - std::lock_guard<std::mutex> g(lock); - logger->messagebf(LOG::DEBUG, "%s: Searching for an open sharable tuner any frequency", __PRETTY_FUNCTION__); - auto openTuner = std::find_if(devices.begin(), devices.end(), [delivery](const Devices::value_type & ot) { - return ot.second && !ot.second->openedPrivate && ot.second->delivery; - }); - if (openTuner != devices.end()) { - openTuner->second->clients += 1; - return openTuner->second->tuner; - } - - openTuner = std::find_if(devices.begin(), devices.end(), [](const Devices::value_type & ot) { return !ot.second; }); - if (openTuner == devices.end()) { - logger->messagebf(LOG::DEBUG, "%s: None suitable and none free (frequency %d)", - __PRETTY_FUNCTION__, delivery->Frequency); - throw NoSuitableDeviceAvailable(); - } - - logger->messagebf(LOG::DEBUG, "%s: Opening a sharable tuner (frequency %d, frontend %s)", - __PRETTY_FUNCTION__, delivery->Frequency, openTuner->first); - PrivateTunerPtr t = new DVB::Tuner(openTuner->first); - t->TuneTo(delivery, ice); - auto tuner = PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(t)); - openTuner->second = OpenTunerPtr(new OpenTuner(delivery, tuner, false)); - - logger->messagebf(LOG::DEBUG, "%s: Tuned, returning (frequency %d, frontend %s)", - __PRETTY_FUNCTION__, delivery->Frequency, openTuner->first); - return tuner; -} - -PrivateTunerPrx -LocalDevicesI::GetPrivateTuner(short , const Ice::Current & ice) -{ - std::lock_guard<std::mutex> g(lock); - logger->messagebf(LOG::DEBUG, "%s: Opening a private tuner", __PRETTY_FUNCTION__); - auto openTuner = std::find_if(devices.begin(), devices.end(), [](const Devices::value_type & ot) { return !ot.second; }); - if (openTuner == devices.end()) { - logger->messagebf(LOG::DEBUG, "%s: None free", __PRETTY_FUNCTION__); - throw NoSuitableDeviceAvailable(); - } - - logger->messagebf(LOG::DEBUG, "%s: Opening a private tuner (frontend %s)", - __PRETTY_FUNCTION__, openTuner->first); - auto tuner = PrivateTunerPrx::checkedCast(ice.adapter->addWithUUID(new DVB::Tuner(openTuner->first))); - openTuner->second = OpenTunerPtr(new OpenTuner(NULL, tuner, true)); - - return tuner; -} - -void -LocalDevicesI::ReleaseTuner(const TunerPrx & tuner, const Ice::Current & ice) -{ - std::lock_guard<std::mutex> g(lock); - logger->messagebf(LOG::DEBUG, "%s", __PRETTY_FUNCTION__); - auto openTuner = std::find_if(devices.begin(), devices.end(), [tuner](const Devices::value_type & ot) { - return ot.second && ot.second->tuner == tuner; - }); - if (openTuner == devices.end()) { - logger->messagebf(LOG::DEBUG, "%s: Not one of mine", __PRETTY_FUNCTION__); - return; - } - logger->messagebf(LOG::DEBUG, "%s: Locally owned deivce %s", __PRETTY_FUNCTION__, openTuner->first); - openTuner->second->clients -= 1; - if (openTuner->second->clients == 0) { - auto id = tuner->ice_getIdentity(); - if (ice.adapter->find(id)) { - ice.adapter->remove(id); - } - openTuner->second.reset(); - } -} - -int -LocalDevicesI::TunerCount(const Ice::Current &) -{ - std::lock_guard<std::mutex> g(lock); - return devices.size(); -} - -void -LocalDevicesI::Scan(const Ice::Current &) -{ - std::lock_guard<std::mutex> g(lock); -} - -void -LocalDevicesI::Add(const std::string & frontend, const Ice::Current &) -{ - std::lock_guard<std::mutex> g(lock); - devices.insert(Devices::value_type(frontend, OpenTunerPtr())); -} - -void -LocalDevicesI::Remove(const std::string & frontend, const Ice::Current &) -{ - std::lock_guard<std::mutex> g(lock); - devices.erase(frontend); -} - -LocalDevicesI::OpenTuner::OpenTuner(DVBSI::DeliveryPtr d, PrivateTunerPrx t, bool op) : - openedPrivate(op), - delivery(d), - tuner(t), - clients(1) -{ -} -} - diff --git a/p2pvr/devices/localDevices.h b/p2pvr/devices/localDevices.h deleted file mode 100644 index 0fd4ad2..0000000 --- a/p2pvr/devices/localDevices.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef LOCALDEVICES_H -#define LOCALDEVICES_H - -// Local devices implements a device collection (Devices) for any devices physically -// attached to the local machine; that is, can be accessed directly through /dev/dvb/adapterX - -#include <dvb.h> -#include <options.h> -#include <mutex> -#include <visibility.h> -#include <IceUtil/Timer.h> -#include <logger.h> - -namespace P2PVR { -class DLL_PUBLIC LocalDevicesI : public LocalDevices { - public: - class Options : public IceTray::Options { - public: - Options(); - - ICETRAY_OPTIONS_DECLARE; - - std::vector<std::string> devices; - }; - - LocalDevicesI(Ice::ObjectAdapterPtr adapter, IceUtil::TimerPtr); - ~LocalDevicesI(); - - TunerPrx GetTunerSpecific(const DVBSI::DeliveryPtr &, const Ice::Current &); - TunerPrx GetTunerAny(const DVBSI::DeliveryPtr &, const Ice::Current &); - PrivateTunerPrx GetPrivateTuner(short type, const Ice::Current &); - void ReleaseTuner(const TunerPrx &, const Ice::Current &); - int TunerCount(const Ice::Current &); - - void Scan(const Ice::Current &); - void Add(const std::string & frontend, const Ice::Current &); - void Remove(const std::string & frontend, const Ice::Current &); - - private: - // Reference to global timer - IceUtil::TimerPtr timer; - IceUtil::TimerTaskPtr clientCheck; - - // Check that registered clients haven't silently gone away - DLL_PRIVATE void ClientCheck(Ice::ObjectAdapterPtr adapter); - - class DLL_PRIVATE OpenTuner { - public: - OpenTuner(DVBSI::DeliveryPtr, PrivateTunerPrx, bool); - - const bool openedPrivate; - const DVBSI::DeliveryPtr delivery; - const PrivateTunerPrx tuner; - - unsigned int clients; - }; - typedef boost::shared_ptr<OpenTuner> OpenTunerPtr; - typedef std::map<std::string, OpenTunerPtr> Devices; - static Devices devices; - static std::mutex lock; - static IceTray::Logging::LoggerPtr logger; - IceTray::OptionsResolver<Options> options; -}; -} - -#endif - diff --git a/p2pvr/devices/mockTuner.cpp b/p2pvr/devices/mockTuner.cpp index 4430bc4..1316b6d 100644 --- a/p2pvr/devices/mockTuner.cpp +++ b/p2pvr/devices/mockTuner.cpp @@ -31,6 +31,7 @@ ResourceFile(pmt); ResourceFile(vid); int MockTuner::eventSet = 0; +int MockTuner::senderId = 1; IceTray::Logging::LoggerPtr MockTuner::logger = LOGMANAGER()->getLogger<MockTuner>(); @@ -40,16 +41,21 @@ MockTuner::SetEventsSet(int n) eventSet = n; } -MockTuner::MockTuner() : - senderId(1) +MockTuner::MockTuner(Ice::CommunicatorPtr c) : + ic(c) { } -void MockTuner::TuneTo(const DVBSI::DeliveryPtr &, const Ice::Current&) +void MockTuner::TuneTo(const DVBSI::DeliveryPtr &) { } -int MockTuner::GetStatus(const Ice::Current&) +int MockTuner::GetStatus() +{ + return 0; +} + +std::string MockTuner::GetDevice() { return 0; } @@ -80,11 +86,11 @@ Ice::ByteSeq MockTuner::Decompress(const Ice::ByteSeq & dataxz) return data; } -void MockTuner::DecompressAndSendPackets(const Ice::ByteSeq & dataxz, const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) const +void MockTuner::DecompressAndSendPackets(const Ice::ByteSeq & dataxz, const P2PVR::RawDataClientPrx & client) const { logger->messagebf(LOG::DEBUG, "%s: deserialize", __PRETTY_FUNCTION__); std::list<Ice::ByteSeq> packets; - auto istrm = Ice::createInputStream(ice.adapter->getCommunicator(), Decompress(dataxz)); + auto istrm = Ice::createInputStream(ic, Decompress(dataxz)); istrm->read(packets); logger->messagebf(LOG::DEBUG, "%s: send", __PRETTY_FUNCTION__); @@ -95,42 +101,42 @@ void MockTuner::DecompressAndSendPackets(const Ice::ByteSeq & dataxz, const P2PV logger->messagebf(LOG::DEBUG, "%s: complete", __PRETTY_FUNCTION__); } -void MockTuner::ScanAndSendNetworkInformation(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) +void MockTuner::ScanAndSendNetworkInformation(const P2PVR::RawDataClientPrx & client) { - DecompressAndSendPackets(network, client, ice); + DecompressAndSendPackets(network, client); } -void MockTuner::SendNetworkInformation(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) +void MockTuner::SendNetworkInformation(const P2PVR::RawDataClientPrx & client) { - DecompressAndSendPackets(network, client, ice); + DecompressAndSendPackets(network, client); } -void MockTuner::SendBouquetAssociations(const P2PVR::RawDataClientPrx &, const Ice::Current&) +void MockTuner::SendBouquetAssociations(const P2PVR::RawDataClientPrx &) { } -void MockTuner::SendServiceDescriptions(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) +void MockTuner::SendServiceDescriptions(const P2PVR::RawDataClientPrx & client) { - DecompressAndSendPackets(services, client, ice); + DecompressAndSendPackets(services, client); } -void MockTuner::SendProgramMap(Ice::Int, const P2PVR::RawDataClientPrx &, const Ice::Current&) +void MockTuner::SendProgramMap(Ice::Int, const P2PVR::RawDataClientPrx &) { } -void MockTuner::SendProgramAssociationTable(const P2PVR::RawDataClientPrx &, const Ice::Current&) +void MockTuner::SendProgramAssociationTable(const P2PVR::RawDataClientPrx &) { } -void MockTuner::SendEventInformation(const P2PVR::RawDataClientPrx & client, const Ice::Current & ice) +void MockTuner::SendEventInformation(const P2PVR::RawDataClientPrx & client) { - DecompressAndSendPackets(eventSet == 0 ? events1 : events2, client, ice); + DecompressAndSendPackets(eventSet == 0 ? events1 : events2, client); } -void MockTuner::SendLoop(const P2PVR::RawDataClientPrx & t, const Ice::ByteSeq & dataxz, const Ice::Current & ice) const +void MockTuner::SendLoop(const P2PVR::RawDataClientPrx & t, const Ice::ByteSeq & dataxz) const { std::list<Ice::ByteSeq> packets; - auto istrm = Ice::createInputStream(ice.adapter->getCommunicator(), Decompress(dataxz)); + auto istrm = Ice::createInputStream(ic, Decompress(dataxz)); istrm->read(packets); logger->messagebf(LOG::DEBUG, "%s: loop over %d packets", __PRETTY_FUNCTION__, packets.size()); auto p = packets.begin(); @@ -149,23 +155,23 @@ void MockTuner::SendLoop(const P2PVR::RawDataClientPrx & t, const Ice::ByteSeq & } -int MockTuner::StartSendingTS(const P2PVR::PacketIds &, const P2PVR::RawDataClientPrx & t, const Ice::Current & ice) +int MockTuner::StartSendingTS(const P2PVR::PacketIds &, const P2PVR::RawDataClientPrx & t) { - return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, vid, ice)}).first->first; + return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, vid)}).first->first; } -int MockTuner::StartSendingSection(Ice::Int sid, const P2PVR::RawDataClientPrx & t, const Ice::Current & ice) +int MockTuner::StartSendingSection(Ice::Int sid, const P2PVR::RawDataClientPrx & t) { switch (sid) { case 0: // pat - return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, pat, ice)}).first->first; + return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, pat)}).first->first; case 100: // sample pmt - return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, pmt, ice)}).first->first; + return senders.insert({senderId++, new boost::thread(&MockTuner::SendLoop, this, t, pmt)}).first->first; } throw std::runtime_error("I don't have a sample for that"); } -void MockTuner::StopSending(int s, const Ice::Current &) +void MockTuner::StopSending(int s) { logger->messagebf(LOG::DEBUG, "%s: stop %d", __PRETTY_FUNCTION__, s); auto sitr = senders.find(s); @@ -175,11 +181,6 @@ void MockTuner::StopSending(int s, const Ice::Current &) senders.erase(sitr); } } - -Ice::Long MockTuner::GetLastUsedTime(const Ice::Current&) -{ - return time(NULL); -} } } diff --git a/p2pvr/devices/mockTuner.h b/p2pvr/devices/mockTuner.h index 73ab27c..d0db11e 100644 --- a/p2pvr/devices/mockTuner.h +++ b/p2pvr/devices/mockTuner.h @@ -9,38 +9,38 @@ namespace P2PVR { namespace Testing { -class DLL_PUBLIC MockTuner : public PrivateTuner { +class DLL_PUBLIC MockTuner : public Tuner { public: - MockTuner(); + MockTuner(Ice::CommunicatorPtr); - void TuneTo(const DVBSI::DeliveryPtr &, const Ice::Current&); - int GetStatus(const Ice::Current&); + void TuneTo(const DVBSI::DeliveryPtr &) override; + int GetStatus() override; + std::string GetDevice() override; - void ScanAndSendNetworkInformation(const RawDataClientPrx & client, const Ice::Current&); - void SendNetworkInformation(const RawDataClientPrx & client, const Ice::Current&); - void SendBouquetAssociations(const RawDataClientPrx & client, const Ice::Current&); - void SendServiceDescriptions(const RawDataClientPrx & client, const Ice::Current&); - void SendProgramMap(Ice::Int pid, const RawDataClientPrx & client, const Ice::Current&); - void SendProgramAssociationTable(const RawDataClientPrx & client, const Ice::Current&); - void SendEventInformation(const RawDataClientPrx & client, const Ice::Current&); + void ScanAndSendNetworkInformation(const RawDataClientPrx & client) override; + void SendNetworkInformation(const RawDataClientPrx & client) override; + void SendBouquetAssociations(const RawDataClientPrx & client) override; + void SendServiceDescriptions(const RawDataClientPrx & client) override; + void SendProgramMap(Ice::Int pid, const RawDataClientPrx & client) override; + void SendProgramAssociationTable(const RawDataClientPrx & client) override; + void SendEventInformation(const RawDataClientPrx & client) override; - int StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client, const Ice::Current &); - int StartSendingSection(Ice::Int pid, const RawDataClientPrx & client, const Ice::Current &); - void StopSending(int handle, const Ice::Current &); - - Ice::Long GetLastUsedTime(const Ice::Current&); + int StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client) override; + int StartSendingSection(Ice::Int pid, const RawDataClientPrx & client) override; + void StopSending(int handle) override; static void SetEventsSet(int n); protected: static Ice::ByteSeq Decompress(const Ice::ByteSeq &); static void LZMA_ASSERT(int ret_xz); - void DecompressAndSendPackets(const Ice::ByteSeq &, const RawDataClientPrx &, const Ice::Current&) const; - void SendLoop(const RawDataClientPrx & t, const Ice::ByteSeq & dataxz, const Ice::Current & ice) const; + void DecompressAndSendPackets(const Ice::ByteSeq &, const RawDataClientPrx &) const; + void SendLoop(const RawDataClientPrx & t, const Ice::ByteSeq & dataxz) const; static int eventSet; std::map<int, boost::thread *> senders; - int senderId; + static int senderId; + Ice::CommunicatorPtr ic; static IceTray::Logging::LoggerPtr logger; }; diff --git a/p2pvr/devices/tuner.cpp b/p2pvr/devices/tuner.cpp index 73dcd67..bb27a44 100644 --- a/p2pvr/devices/tuner.cpp +++ b/p2pvr/devices/tuner.cpp @@ -8,19 +8,19 @@ #include <linux/dvb/dmx.h> #include <boost/tuple/tuple.hpp> #include <cxxabi.h> +#include <lockHelpers.h> #include "tunerSendSi.h" #include "tunerSendTs.h" namespace P2PVR { namespace DVB { -IceTray::Logging::LoggerPtr Tuner::logger = LOGMANAGER()->getLogger<Tuner>(); +IceTray::Logging::LoggerPtr TunerI::logger = LOGMANAGER()->getLogger<TunerI>(); -Tuner::Tuner(const boost::filesystem::path & df) : +TunerI::TunerI(const boost::filesystem::path & df) : deviceFrontend(df), deviceRoot(df.branch_path()), frontendFD(deviceFrontend, O_RDWR), - backgroundThread(NULL), - lastUsedTime(time(NULL)) + backgroundThread(NULL) { struct dvb_frontend_info fe_info; if (ioctl(frontendFD, FE_GET_INFO, &fe_info) < 0) { @@ -31,7 +31,7 @@ Tuner::Tuner(const boost::filesystem::path & df) : deviceRoot, frontend->Info().name, frontend->Type()); } -Tuner::~Tuner() +TunerI::~TunerI() { { std::lock_guard<std::mutex> g(lock); @@ -47,27 +47,25 @@ Tuner::~Tuner() } void -Tuner::TuneTo(const DVBSI::DeliveryPtr & mp, const Ice::Current&) +TunerI::TuneTo(const DVBSI::DeliveryPtr & mp) { frontend->TuneTo(mp); } int -Tuner::GetStatus(const Ice::Current &) +TunerI::GetStatus() { - time(&lastUsedTime); return frontend->GetStatus(); } std::string -Tuner::Device() const +TunerI::GetDevice() { - time(&lastUsedTime); return deviceRoot.string(); } int -Tuner::OpenDemux() const +TunerI::OpenDemux() const { int demux = open((deviceRoot / "demux0").string().c_str(), O_RDWR | O_NONBLOCK); if (demux < 0) { @@ -77,12 +75,11 @@ Tuner::OpenDemux() const } void -Tuner::ScanAndSendNetworkInformation(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::ScanAndSendNetworkInformation(const RawDataClientPrx & client) { - time(&lastUsedTime); - frontend->FrequencyScan([this, &client, &ice](long) { + frontend->FrequencyScan([this, &client](long) { try { - return (SendPID(0x10, client, ice) > 0); + return (SendPID(0x10, client) > 0); } catch (const std::exception & ex) { char * buf = __cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL); @@ -98,57 +95,53 @@ Tuner::ScanAndSendNetworkInformation(const RawDataClientPrx & client, const Ice: } void -Tuner::SendNetworkInformation(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendNetworkInformation(const RawDataClientPrx & client) { - SendPID(0x10, client, ice); + SendPID(0x10, client); } void -Tuner::SendBouquetAssociations(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendBouquetAssociations(const RawDataClientPrx & client) { - SendPID(0x11, client, ice); + SendPID(0x11, client); } void -Tuner::SendServiceDescriptions(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendServiceDescriptions(const RawDataClientPrx & client) { - SendPID(0x11, client, ice); + SendPID(0x11, client); } void -Tuner::SendProgramMap(Ice::Int pid, const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendProgramMap(Ice::Int pid, const RawDataClientPrx & client) { - SendPID(pid, client, ice); + SendPID(pid, client); } void -Tuner::SendProgramAssociationTable(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendProgramAssociationTable(const RawDataClientPrx & client) { - SendPID(0x00, client, ice); + SendPID(0x00, client); } void -Tuner::SendEventInformation(const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::SendEventInformation(const RawDataClientPrx & client) { - SendPID(0x12, client, ice); + SendPID(0x12, client); } uint64_t -Tuner::SendPID(int pid, const RawDataClientPrx & client, const Ice::Current & ice) const +TunerI::SendPID(int pid, const RawDataClientPrx & client) const { - time(&lastUsedTime); logger->messagebf(LOG::DEBUG, "%s: pid = 0x%x", __PRETTY_FUNCTION__, pid); - if (ice.con) { - ice.con->createProxy(client->ice_getIdentity()); - } AdHoc::FileUtils::FileHandle demux(OpenDemux()); RequestPID(pid, demux); return ReadDemuxAndSend(demux, client); } void -Tuner::RequestPID(int pid, int demux) const +TunerI::RequestPID(int pid, int demux) const { setBufferSize(demux, options->DemuxTableBufferSize); struct dmx_sct_filter_params sctFilterParams; @@ -162,7 +155,7 @@ Tuner::RequestPID(int pid, int demux) const } uint64_t -Tuner::ReadDemuxAndSend(int demux, const RawDataClientPrx & _client) const +TunerI::ReadDemuxAndSend(int demux, const RawDataClientPrx & _client) const { logger->messagebf(LOG::DEBUG, "%s: begin", __PRETTY_FUNCTION__); struct pollfd ufd; @@ -194,7 +187,6 @@ Tuner::ReadDemuxAndSend(int demux, const RawDataClientPrx & _client) const buf.resize(n); client->NewData(buf); - time(&lastUsedTime); } while (!client->IsFinished()); auto packetsSent = client->PacketsSent(); @@ -204,12 +196,11 @@ Tuner::ReadDemuxAndSend(int demux, const RawDataClientPrx & _client) const } int -Tuner::StartSendingSection(int pid, const RawDataClientPrx & client, const Ice::Current &) +TunerI::StartSendingSection(int pid, const RawDataClientPrx & client) { - time(&lastUsedTime); logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); - std::lock_guard<std::mutex> g(lock); + Lock(lock); int demux = backgroundClients.insert(BackgroundClients::value_type(OpenDemux(), BackgroundClient(new SendSi(client)))).first->first; RequestPID(pid, demux); @@ -218,18 +209,14 @@ Tuner::StartSendingSection(int pid, const RawDataClientPrx & client, const Ice:: } int -Tuner::StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client, const Ice::Current & ice) +TunerI::StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client) { - time(&lastUsedTime); logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); if (pids.empty()) { throw DeviceError("demux", "Packet Id list cannot be empty", 0); } - if (ice.con) { - ice.con->createProxy(client->ice_getIdentity()); - } - std::lock_guard<std::mutex> g(lock); + Lock(lock); int demux = backgroundClients.insert(BackgroundClients::value_type(OpenDemux(), BackgroundClient(new SendTs(client)))).first->first; @@ -270,7 +257,7 @@ Tuner::StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client, c } void -Tuner::setBufferSize(int demux, unsigned long size) +TunerI::setBufferSize(int demux, unsigned long size) { if (ioctl(demux, DMX_SET_BUFFER_SIZE, size)) { logger->messagebf(LOG::ERR, "%s: DMX_SET_BUFFER_SIZE to %d failed (%d: %s)", __PRETTY_FUNCTION__, size, errno, strerror(errno)); @@ -280,9 +267,8 @@ Tuner::setBufferSize(int demux, unsigned long size) } void -Tuner::StopSending(int handle, const Ice::Current &) +TunerI::StopSending(int handle) { - time(&lastUsedTime); logger->message(LOG::DEBUG, __PRETTY_FUNCTION__); std::lock_guard<std::mutex> g(lock); if (backgroundClients.find(handle) != backgroundClients.end()) { @@ -292,15 +278,15 @@ Tuner::StopSending(int handle, const Ice::Current &) } void -Tuner::startSenderThread() +TunerI::startSenderThread() { if (!backgroundThread) { - backgroundThread = new std::thread(&Tuner::senderThread, this); + backgroundThread = new std::thread(&TunerI::senderThread, this); } } void -Tuner::senderThread() +TunerI::senderThread() { lock.lock(); while (!backgroundClients.empty()) { @@ -311,7 +297,6 @@ Tuner::senderThread() FD_SET(c.first, &rfds); } lock.unlock(); - time(&lastUsedTime); struct timeval tv { 2, 0 }; switch (select(n, &rfds, NULL, NULL, &tv)) { @@ -361,38 +346,32 @@ Tuner::senderThread() backgroundThread = NULL; logger->messagebf(LOG::DEBUG, "%s: Unlocking", __PRETTY_FUNCTION__); lock.unlock(); -} - -Ice::Long -Tuner::GetLastUsedTime(const Ice::Current &) -{ - return lastUsedTime; } -Tuner::IDataSender::IDataSender(const RawDataClientPrx & c) : +TunerI::IDataSender::IDataSender(const RawDataClientPrx & c) : _packetsSent(0), client(c) { } -Tuner::IDataSender::~IDataSender() +TunerI::IDataSender::~IDataSender() { } uint64_t -Tuner::IDataSender::PacketsSent() const +TunerI::IDataSender::PacketsSent() const { return _packetsSent; } -Tuner::Options::Options() : +TunerI::Options::Options() : IceTray::Options("P2PVR Tuner Options") { } namespace po = boost::program_options; -ICETRAY_OPTIONS(Tuner::Options, +ICETRAY_OPTIONS(TunerI::Options, ("p2pvr.tuner.tuningtimeout", po::value(&TuningTimeout)->default_value(500), "Timeout for a DVB frontend to tune (ms, default 500ms)") ("p2pvr.tuner.locktimeout", po::value(&LockTimeout)->default_value(2000), diff --git a/p2pvr/devices/tuner.h b/p2pvr/devices/tuner.h index b4d92b3..695b322 100644 --- a/p2pvr/devices/tuner.h +++ b/p2pvr/devices/tuner.h @@ -20,7 +20,7 @@ namespace Frontends { class OFDM; } -class Tuner : public PrivateTuner { +class TunerI : public Tuner { public: class IDataSender { public: @@ -38,30 +38,28 @@ class Tuner : public PrivateTuner { typedef boost::shared_ptr<IDataSender> BackgroundClient; typedef std::map<int, BackgroundClient> BackgroundClients; - Tuner(const boost::filesystem::path & deviceFrontend); - ~Tuner(); + TunerI(const boost::filesystem::path & deviceFrontend); + ~TunerI(); - void TuneTo(const DVBSI::DeliveryPtr &, const Ice::Current&); - int GetStatus(const Ice::Current&); - std::string Device() const; + void TuneTo(const DVBSI::DeliveryPtr &) override; + int GetStatus() override; + std::string GetDevice() override; - void ScanAndSendNetworkInformation(const RawDataClientPrx & client, const Ice::Current&); - void SendNetworkInformation(const RawDataClientPrx & client, const Ice::Current&); - void SendBouquetAssociations(const RawDataClientPrx & client, const Ice::Current&); - void SendServiceDescriptions(const RawDataClientPrx & client, const Ice::Current&); - void SendProgramMap(Ice::Int pid, const RawDataClientPrx & client, const Ice::Current&); - void SendProgramAssociationTable(const RawDataClientPrx & client, const Ice::Current&); - void SendEventInformation(const RawDataClientPrx & client, const Ice::Current&); + void ScanAndSendNetworkInformation(const RawDataClientPrx & client) override; + void SendNetworkInformation(const RawDataClientPrx & client) override; + void SendBouquetAssociations(const RawDataClientPrx & client) override; + void SendServiceDescriptions(const RawDataClientPrx & client) override; + void SendProgramMap(Ice::Int pid, const RawDataClientPrx & client) override; + void SendProgramAssociationTable(const RawDataClientPrx & client) override; + void SendEventInformation(const RawDataClientPrx & client) override; - int StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client, const Ice::Current &); - int StartSendingSection(Ice::Int pid, const RawDataClientPrx & client, const Ice::Current &); - void StopSending(int handle, const Ice::Current &); - - Ice::Long GetLastUsedTime(const Ice::Current&); + int StartSendingTS(const PacketIds & pids, const RawDataClientPrx & client) override; + int StartSendingSection(Ice::Int pid, const RawDataClientPrx & client) override; + void StopSending(int handle) override; private: int OpenDemux() const; - uint64_t SendPID(int pid, const RawDataClientPrx & client, const Ice::Current &) const; + uint64_t SendPID(int pid, const RawDataClientPrx & client) const; void RequestPID(int pid, int fd) const; uint64_t ReadDemuxAndSend(int fd, const RawDataClientPrx & client) const; void startSenderThread(); @@ -75,7 +73,6 @@ class Tuner : public PrivateTuner { std::thread * backgroundThread; std::mutex lock; - mutable time_t lastUsedTime; FrontendPtr frontend; static IceTray::Logging::LoggerPtr logger; diff --git a/p2pvr/devices/tunerSendSi.cpp b/p2pvr/devices/tunerSendSi.cpp index 0215e47..3e09aaf 100644 --- a/p2pvr/devices/tunerSendSi.cpp +++ b/p2pvr/devices/tunerSendSi.cpp @@ -8,7 +8,7 @@ namespace DVB { IceTray::Logging::LoggerPtr SendSi::logger(LOGMANAGER()->getLogger<SendSi>()); SendSi::SendSi(const RawDataClientPrx & c) : - Tuner::IDataSender(c->ice_collocationOptimized(false)) + TunerI::IDataSender(c->ice_collocationOptimized(false)) { } diff --git a/p2pvr/devices/tunerSendSi.h b/p2pvr/devices/tunerSendSi.h index 8b146ff..688fb2a 100644 --- a/p2pvr/devices/tunerSendSi.h +++ b/p2pvr/devices/tunerSendSi.h @@ -6,7 +6,7 @@ namespace P2PVR { namespace DVB { -class SendSi : public Tuner::IDataSender { +class SendSi : public TunerI::IDataSender { public: SendSi(const P2PVR::RawDataClientPrx &); ~SendSi(); diff --git a/p2pvr/devices/tunerSendTs.cpp b/p2pvr/devices/tunerSendTs.cpp index 8005311..fef418f 100644 --- a/p2pvr/devices/tunerSendTs.cpp +++ b/p2pvr/devices/tunerSendTs.cpp @@ -11,7 +11,7 @@ namespace DVB { IceTray::Logging::LoggerPtr SendTs::logger(LOGMANAGER()->getLogger<SendTs>()); SendTs::SendTs(const RawDataClientPrx & c) : - Tuner::IDataSender(c->ice_collocationOptimized(false)) + TunerI::IDataSender(c->ice_collocationOptimized(false)) { buffer.reserve(TARGET_BUFFER_SIZE); } diff --git a/p2pvr/devices/tunerSendTs.h b/p2pvr/devices/tunerSendTs.h index cd74198..bbec0a9 100644 --- a/p2pvr/devices/tunerSendTs.h +++ b/p2pvr/devices/tunerSendTs.h @@ -6,7 +6,7 @@ namespace P2PVR { namespace DVB { -class SendTs : public Tuner::IDataSender { +class SendTs : public TunerI::IDataSender { public: SendTs(const P2PVR::RawDataClientPrx &); ~SendTs(); diff --git a/p2pvr/dvb/unittests/createBroadcast.cpp b/p2pvr/dvb/unittests/createBroadcast.cpp index ee147f2..d381641 100644 --- a/p2pvr/dvb/unittests/createBroadcast.cpp +++ b/p2pvr/dvb/unittests/createBroadcast.cpp @@ -29,7 +29,7 @@ class Core { { adapter->activate(); - devs = DevicesPrx::checkedCast(ic->stringToProxy("Devices:tcp -h defiant -p 10000")); + devs = TunersPrx::checkedCast(ic->stringToProxy("Devices:tcp -h defiant -p 10000")); BOOST_REQUIRE(devs); devs->ice_ping(); } @@ -39,7 +39,7 @@ class Core { ic->destroy(); } - DevicesPrx devs; + TunersPrx devs; Ice::CommunicatorPtr ic; Ice::ObjectAdapterPtr adapter; @@ -47,7 +47,7 @@ class Core { class Sampler { public: - Sampler(int sid, DevicesPrx d, Ice::ObjectAdapterPtr a) : + Sampler(int sid, TunersPrx d, Ice::ObjectAdapterPtr a) : patp(a, new DVBSI::BindDataHandler(boost::bind(&Sampler::Handle, this, _1, boost::ref(pat)))), pmtp(a, new DVBSI::BindDataHandler(boost::bind(&Sampler::Handle, this, _1, boost::ref(pmt)))), vidp(a, new DVBSI::BindDataHandler(boost::bind(&Sampler::Handle, this, _1, boost::ref(vid)))), @@ -107,11 +107,6 @@ BOOST_AUTO_TEST_CASE( broadcast_sample ) BOOST_REQUIRE_EQUAL(transport->Frequency, 682000000); BOOST_REQUIRE_EQUAL(transport->TransmissionMode, 1); - BOOST_TEST_CHECKPOINT("Acquire device"); - P2PVR::TunerPrx tuner = devs->GetTunerSpecific(transport); - BOOST_REQUIRE(tuner); - tuner->ice_ping(); - BOOST_TEST_CHECKPOINT("Create sampler"); P2PVR::Testing::Sampler sampler(4170, devs, adapter); diff --git a/p2pvr/dvb/unittests/createSamples.cpp b/p2pvr/dvb/unittests/createSamples.cpp index 6c477c9..3c07620 100644 --- a/p2pvr/dvb/unittests/createSamples.cpp +++ b/p2pvr/dvb/unittests/createSamples.cpp @@ -63,7 +63,7 @@ class SiSampleCollector : public Base { template <class Base, class Object> static void -CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<void(TunerPrx, RawDataClientPrx)> & method) +CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<void(TunersPrx, ::DVBSI::DeliveryPtr, RawDataClientPrx)> & method) { auto icp = standardConfig<SiSampleCollector<Base, Object>>(); auto ic = boost::get<0>(icp); @@ -71,7 +71,7 @@ CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<v auto p = boost::get<2>(icp); AdHoc::ScopeExit _([&ic]{ ic->destroy(); }); - auto devs = DevicesPrx::checkedCast(ic->stringToProxy("Devices:tcp -h defiant -p 10000")); + auto devs = TunersPrx::checkedCast(ic->stringToProxy("Devices:tcp -h defiant -p 10000")); auto parser = RawDataClientPrx::checkedCast(adap->createProxy(ic->stringToIdentity("parser"))); BOOST_REQUIRE(devs); devs->ice_ping(); @@ -85,15 +85,9 @@ CaptureAndSave(const boost::filesystem::path & fileName, const boost::function<v BOOST_REQUIRE_EQUAL(transport->TransmissionMode, 1); BOOST_TEST_CHECKPOINT("Acquire device"); - TunerPrx tuner = devs->GetTunerAny(transport); - BOOST_REQUIRE(tuner); - tuner->ice_ping(); BOOST_TEST_CHECKPOINT("Get data"); - method(tuner, parser); - - BOOST_TEST_CHECKPOINT("Release device"); - devs->ReleaseTuner(tuner); + method(devs, transport, parser); BOOST_TEST_MESSAGE("Total packets: " << p->packets.size()); BOOST_REQUIRE(p->packets.size() > 0); @@ -118,18 +112,18 @@ using namespace P2PVR::DVBSI; BOOST_AUTO_TEST_CASE( network_sample ) { CaptureAndSave<SiNetworkInformationParser, ::DVBSI::NetworkPtr>("network.dat", - [](TunerPrx t, RawDataClientPrx rdc) { t->SendNetworkInformation(rdc); }); + [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendNetworkInformation(del, rdc); }); } BOOST_AUTO_TEST_CASE( services_sample ) { CaptureAndSave<SiServicesParser, ::DVBSI::TransportStreamPtr>("services.dat", - [](TunerPrx t, RawDataClientPrx rdc) { t->SendServiceDescriptions(rdc); }); + [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendServiceDescriptions(del, rdc); }); } BOOST_AUTO_TEST_CASE( events_sample ) { CaptureAndSave<SiEpgParser, ::DVBSI::EventPtr>("events.dat", - [](TunerPrx t, RawDataClientPrx rdc) { t->SendEventInformation(rdc); }); + [](TunersPrx t, ::DVBSI::DeliveryPtr del, RawDataClientPrx rdc) { t->SendEventInformation(del, rdc); }); } diff --git a/p2pvr/ice/dvb.ice b/p2pvr/ice/dvb.ice index b306d1e..3c6ef87 100644 --- a/p2pvr/ice/dvb.ice +++ b/p2pvr/ice/dvb.ice @@ -14,6 +14,8 @@ module P2PVR { exception IncorrectDeliveryType { }; + exception NoSuitableDeviceAvailable { }; + sequence<byte> Data; sequence<short> PacketIds; @@ -21,9 +23,9 @@ module P2PVR { bool NewData(Data bytes) throws DataHandlingException; }; - interface Tuner { + local interface Tuner { idempotent int GetStatus(); - idempotent long GetLastUsedTime(); + idempotent string GetDevice(); idempotent void SendNetworkInformation(RawDataClient * client) throws DeviceError, DataHandlingException; idempotent void SendBouquetAssociations(RawDataClient * client) throws DeviceError, DataHandlingException; @@ -35,35 +37,32 @@ module P2PVR { int StartSendingTS(PacketIds pids, RawDataClient * client); int StartSendingSection(int pid, RawDataClient * client); idempotent void StopSending(int handle); - }; - - interface PrivateTuner extends Tuner { idempotent void TuneTo(DVBSI::Delivery d) throws DeviceError; idempotent void ScanAndSendNetworkInformation(RawDataClient * client) throws DeviceError, DataHandlingException; }; - exception NoSuitableDeviceAvailable { }; - - interface Devices { - // Get a tuner that is tuned to <del>, acquire and tune to <del> if required. - Tuner * GetTunerSpecific(DVBSI::Delivery del); - // Get any tuner that is tuned, acquire and tune to <del> if required. - Tuner * GetTunerAny(DVBSI::Delivery del); - // Get a private tuner, not shared or sharable - PrivateTuner * GetPrivateTuner(short type); - // Release a tuner when no longer required. - idempotent void ReleaseTuner(Tuner * t); - // Count available tuners - idempotent int TunerCount(); - }; - - interface LocalDevices extends Devices { - // Add/remove according to device nodes in /dev/dvb/... - idempotent void Scan(); + interface Tuners { + // Add/remove according to device nodes in "path" + idempotent void Scan(string path); // Add a device idempotent void Add(string frontend); // Remove a device idempotent void Remove(string frontend); + // How many registered devices? + idempotent int TunerCount(); + + idempotent void ScanAndSendNetworkInformation(RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + + idempotent void SendNetworkInformation(DVBSI::Delivery del, RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + idempotent void SendBouquetAssociations(DVBSI::Delivery del, RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + idempotent void SendServiceDescriptions(DVBSI::Delivery del, RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + idempotent void SendProgramAssociationTable(DVBSI::Delivery del, RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + idempotent void SendProgramMap(DVBSI::Delivery del, int pid, RawDataClient * client) throws DeviceError, DataHandlingException, NoSuitableDeviceAvailable; + idempotent void SendEventInformation(DVBSI::Delivery del, RawDataClient * client) throws DeviceError, NoSuitableDeviceAvailable; + + int StartSendingTS(DVBSI::Delivery del, PacketIds pids, RawDataClient * client) throws NoSuitableDeviceAvailable; + int StartSendingSection(DVBSI::Delivery del, int pid, RawDataClient * client) throws NoSuitableDeviceAvailable; + idempotent void StopSending(int handle); }; }; diff --git a/p2pvr/lib/serviceStreamer.cpp b/p2pvr/lib/serviceStreamer.cpp index 7e99008..2b88643 100644 --- a/p2pvr/lib/serviceStreamer.cpp +++ b/p2pvr/lib/serviceStreamer.cpp @@ -1,7 +1,7 @@ #include "serviceStreamer.h" namespace P2PVR { -ServiceStreamer::ServiceStreamer(int sid, RawDataClientPrx t, const DevicesPrx & d, const SIPrx & s, const Ice::ObjectAdapterPtr & a) : +ServiceStreamer::ServiceStreamer(int sid, RawDataClientPrx t, const TunersPrx & d, const SIPrx & s, const Ice::ObjectAdapterPtr & a) : ServiceStreamerCore(sid, t, t, t, d, a), si(s) { diff --git a/p2pvr/lib/serviceStreamer.h b/p2pvr/lib/serviceStreamer.h index 17c7850..165d5a0 100644 --- a/p2pvr/lib/serviceStreamer.h +++ b/p2pvr/lib/serviceStreamer.h @@ -8,7 +8,7 @@ namespace P2PVR { class DLL_PUBLIC ServiceStreamer : public ServiceStreamerCore { public: - ServiceStreamer(int sid, RawDataClientPrx, const DevicesPrx & d, const SIPrx & s, const Ice::ObjectAdapterPtr & a); + ServiceStreamer(int sid, RawDataClientPrx, const TunersPrx & d, const SIPrx & s, const Ice::ObjectAdapterPtr & a); ~ServiceStreamer(); void Start(); diff --git a/p2pvr/lib/serviceStreamerCore.cpp b/p2pvr/lib/serviceStreamerCore.cpp index 6299a89..1c37027 100644 --- a/p2pvr/lib/serviceStreamerCore.cpp +++ b/p2pvr/lib/serviceStreamerCore.cpp @@ -6,7 +6,7 @@ namespace P2PVR { IceTray::Logging::LoggerPtr ServiceStreamerCore::log(LOGMANAGER()->getLogger<ServiceStreamerCore>()); ServiceStreamerCore::ServiceStreamerCore(int sid, RawDataClientPrx pat, RawDataClientPrx pmt, RawDataClientPrx ser, - DevicesPrx d, Ice::ObjectAdapterPtr a) : + TunersPrx d, Ice::ObjectAdapterPtr a) : adapter(a), devs(d), patTarget(pat), @@ -17,7 +17,6 @@ ServiceStreamerCore::ServiceStreamerCore(int sid, RawDataClientPrx pat, RawDataC serviceId(sid), patHandle(0), pmtStream(0), pmtHandle(0), serviceHandle(0) { - } ServiceStreamerCore::~ServiceStreamerCore() @@ -32,7 +31,7 @@ ServiceStreamerCore::HandlePAT(const DVBSI::ProgramAssociationMapPtr & pam) pmtStream = p->second; log->messagef(LOG::DEBUG, "%s: Got ProgramAssociationMap, pmtStream now = %d", __PRETTY_FUNCTION__, pmtStream); stopHandle(pmtHandle); - pmtHandle = tuner->StartSendingSection(pmtStream, pmtParser); + pmtHandle = devs->StartSendingSection(transport, pmtStream, pmtParser); } patTarget->NewData(patParser.Get()->CurrentRawData()); return false; @@ -51,17 +50,17 @@ ServiceStreamerCore::HandlePMT(const ::DVBSI::ProgramMapPtr & pmp) streams = strms; log->messagebf(LOG::DEBUG, "%s: Got ProgramMap, switching to %d streams", __PRETTY_FUNCTION__, streams.size()); stopHandle(serviceHandle); - serviceHandle = tuner->StartSendingTS(PacketIds(streams.begin(), streams.end()), serTarget); + serviceHandle = devs->StartSendingTS(transport, PacketIds(streams.begin(), streams.end()), serTarget); } pmtTarget->NewData(pmtParser.Get()->CurrentRawData()); return false; } void -ServiceStreamerCore::Start(::DVBSI::DeliveryPtr transport) +ServiceStreamerCore::Start(::DVBSI::DeliveryPtr t) { - tuner = devs->GetTunerSpecific(transport); - patHandle = tuner->StartSendingSection(0, patParser); + transport = t; + patHandle = devs->StartSendingSection(transport, 0, patParser); } void @@ -70,15 +69,14 @@ ServiceStreamerCore::Stop() stopHandle(serviceHandle); stopHandle(patHandle); stopHandle(pmtHandle); - devs->ReleaseTuner(tuner); - tuner = NULL; + transport = NULL; } void ServiceStreamerCore::stopHandle(int & handle) { if (handle) { - tuner->StopSending(handle); + devs->StopSending(handle); handle = 0; } } diff --git a/p2pvr/lib/serviceStreamerCore.h b/p2pvr/lib/serviceStreamerCore.h index f8ec1f6..c134fec 100644 --- a/p2pvr/lib/serviceStreamerCore.h +++ b/p2pvr/lib/serviceStreamerCore.h @@ -15,7 +15,7 @@ namespace P2PVR { class DLL_PUBLIC ServiceStreamerCore { public: ServiceStreamerCore(int sid, RawDataClientPrx, RawDataClientPrx, RawDataClientPrx, - DevicesPrx, Ice::ObjectAdapterPtr); + TunersPrx, Ice::ObjectAdapterPtr); virtual ~ServiceStreamerCore(); void Start(::DVBSI::DeliveryPtr); @@ -27,13 +27,13 @@ class DLL_PUBLIC ServiceStreamerCore { void stopHandle(int & handle); const Ice::ObjectAdapterPtr & adapter; - DevicesPrx devs; + TunersPrx devs; RawDataClientPrx patTarget; RawDataClientPrx pmtTarget; RawDataClientPrx serTarget; TemporaryIceAdapterObject<DVBSI::SiTableParserBase> patParser; TemporaryIceAdapterObject<DVBSI::SiTableParserBase> pmtParser; - TunerPrx tuner; + ::DVBSI::DeliveryPtr transport; int serviceId; int patHandle; |