fix "Clearall before scan" handling
[enigma2.git] / lib / dvb / db.cpp
index ad2996f913fa7f1ca984c29494119b260d5eccdc..c0064071a75ba42e4deb22db5b2b88629583117c 100644 (file)
@@ -107,7 +107,14 @@ err:
        return -1;
 }
 
+RESULT eBouquet::setListName(const std::string &name)
+{
+       m_bouquet_name = name;
+       return 0;
+}
+
 eDVBService::eDVBService()
+       :m_flags(0)
 {
 }
 
@@ -187,7 +194,10 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ
                res = 0;
                break;
        case eDVBChannelQuery::tSatellitePosition:
-               res = (ref.getDVBNamespace().get() >> 16) == query.m_int;
+               res = ((unsigned int)ref.getDVBNamespace().get())>>16 == (unsigned int)query.m_int;
+               break;
+       case eDVBChannelQuery::tFlags:
+               res = (m_flags & query.m_int) == query.m_int;
                break;
        case eDVBChannelQuery::tChannelID:
        {
@@ -202,6 +212,9 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ
        case eDVBChannelQuery::tOR:
                res = checkFilter(ref, *query.m_p1) || checkFilter(ref, *query.m_p2);
                break;
+       case eDVBChannelQuery::tAny:
+               res = 1;
+               break;
        }
 
        if (query.m_inverse)
@@ -238,8 +251,11 @@ void eDVBDB::reloadServicelist()
                struct stat s;
                if ( !stat("lamedb", &s) )
                {
-                       rename("lamedb", CONFIGDIR"/enigma2/lamedb" );
-                       reloadServicelist();
+                       if ( !stat(CONFIGDIR"/enigma2", &s) )
+                       {
+                               rename("lamedb", CONFIGDIR"/enigma2/lamedb" );
+                               reloadServicelist();
+                       }
                }
                return;
        }
@@ -308,13 +324,21 @@ void eDVBDB::reloadServicelist()
                                ter.guard_interval = guard_interval;
                                ter.hierarchy = hierarchy;
                                ter.inversion = inversion;
-
                                feparm->setDVBT(ter);
                        } else if (line[1]=='c')
                        {
-                               int frequency, symbol_rate, inversion=0, modulation=3;
-                               sscanf(line+2, "%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation);
-//                             t.setCable(frequency, symbol_rate, inversion, modulation);
+                               eDVBFrontendParametersCable cab;
+                               int frequency, symbol_rate,
+                                       inversion=eDVBFrontendParametersCable::Inversion::Unknown,
+                                       modulation=eDVBFrontendParametersCable::Modulation::Auto,
+                                       fec_inner=eDVBFrontendParametersCable::FEC::fAuto;
+                               sscanf(line+2, "%d:%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation, &fec_inner);
+                               cab.frequency = frequency;
+                               cab.fec_inner = fec_inner;
+                               cab.inversion = inversion;
+                               cab.symbol_rate = symbol_rate;
+                               cab.modulation = modulation;
+                               feparm->setDVBC(cab);
                        }
                }
                addChannelToList(channelid, feparm);
@@ -425,6 +449,7 @@ void eDVBDB::saveServicelist()
                                chid.transport_stream_id.get(), chid.original_network_id.get());
                eDVBFrontendParametersSatellite sat;
                eDVBFrontendParametersTerrestrial ter;
+               eDVBFrontendParametersCable cab;
                if (!ch.m_frontendParameters->getDVBS(sat))
                {
                        fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n",
@@ -440,6 +465,11 @@ void eDVBDB::saveServicelist()
                                ter.code_rate_LP, ter.modulation, ter.transmission_mode,
                                ter.guard_interval, ter.hierarchy, ter.inversion);
                }
+               if (!ch.m_frontendParameters->getDVBC(cab))
+               {
+                       fprintf(f, "\tc %d:%d:%d:%d:%d\n",
+                               cab.frequency, cab.symbol_rate, cab.inversion, cab.modulation, cab.fec_inner);
+               }
                fprintf(f, "/\n");
                channels++;
        }
@@ -456,6 +486,7 @@ void eDVBDB::saveServicelist()
                                0);
 
                fprintf(f, "%s\n", i->second->m_service_name.c_str());
+
                fprintf(f, "p:%s", i->second->m_provider_name.c_str());
 
                // write cached pids
@@ -468,6 +499,9 @@ void eDVBDB::saveServicelist()
                        ca != i->second->m_ca.end(); ++ca)
                        fprintf(f, ",C:%04x", *ca);
 
+               if (i->second->m_flags)
+                       fprintf(f, ",f:%x", i->second->m_flags);
+
                fprintf(f, "\n");
                services++;
        }
@@ -615,7 +649,7 @@ void eDVBDB::reloadBouquets()
                memset(ref.data, 0, sizeof(ref.data));
                ref.type=1;
                ref.flags=7;
-               ref.data[0]=1;
+               ref.data[0]=2;
                ref.path="(type == 2) FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet";
                eBouquet &parent = m_bouquets["bouquets.radio"];
                parent.m_services.push_back(ref);
@@ -636,6 +670,160 @@ eDVBDB::~eDVBDB()
        instance=NULL;
 }
 
+RESULT eDVBDB::removeService(const eServiceReference &ref)
+{
+       if (ref.type == eServiceReference::idDVB)
+       {
+               eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+               std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+               if (it != m_services.end())
+               {
+                       m_services.erase(it);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+RESULT eDVBDB::removeServices(int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
+{
+       return removeServices(eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
+}
+
+RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos)
+{
+       RESULT ret=-1;
+       eDVBNamespace eNs;
+       eTransportStreamID eTsid;
+       eOriginalNetworkID eOnid;
+       std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
+       std::set<eDVBChannelID> removed_chids;
+       while (it != m_channels.end())
+       {
+               const eDVBChannelID &ch = it->first;
+               bool remove=true;
+               int system;
+               it->second.m_frontendParameters->getSystem(system);
+               if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite )
+               {
+                       eDVBFrontendParametersSatellite sat;
+                       it->second.m_frontendParameters->getDVBS(sat);
+                       if ((unsigned int)sat.orbital_position != orbpos)
+                               remove=false;
+               }
+               if ( remove && chid.dvbnamespace != eNs && chid.dvbnamespace != ch.dvbnamespace )
+                       remove=false;
+               if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
+                       remove=false;
+               if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
+                       remove=false;
+               if ( remove )
+               {
+                       eDebug("remove %08x %04x %04x",
+                               ch.dvbnamespace.get(),
+                               ch.original_network_id.get(),
+                               ch.transport_stream_id.get());
+                       removed_chids.insert(it->first);
+                       m_channels.erase(it++);
+               }
+               else
+                       ++it;
+       }
+       if (!removed_chids.empty())
+       {
+               std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+               while(service != m_services.end())
+               {
+                       eDVBChannelID chid;
+                       service->first.getChannelID(chid);
+                       std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
+                       if (it != removed_chids.end())
+                               m_services.erase(service++);
+                       else
+                               ++service;
+                       ret=0;
+               }
+       }
+       return ret;
+}
+
+RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask)
+{
+       if (ref.type == eServiceReference::idDVB)
+       {
+               eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+               std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+               if (it != m_services.end())
+                       it->second->m_flags |= ~flagmask;
+               return 0;
+       }
+       return -1;
+}
+
+RESULT eDVBDB::removeFlag(const eServiceReference &ref, unsigned int flagmask)
+{
+       if (ref.type == eServiceReference::idDVB)
+       {
+               eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+               std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+               if (it != m_services.end())
+                       it->second->m_flags &= ~flagmask;
+               return 0;
+       }
+       return -1;
+}
+
+RESULT eDVBDB::removeFlags(unsigned int flagmask, int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
+{
+       return removeFlags(flagmask, eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
+}
+
+RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orbpos)
+{
+       eDVBNamespace eNs;
+       eTransportStreamID eTsid;
+       eOriginalNetworkID eOnid;
+       std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
+       std::set<eDVBChannelID> removed_chids;
+       while (it != m_channels.end())
+       {
+               const eDVBChannelID &ch = it->first;
+               bool remove=true;
+               int system;
+               it->second.m_frontendParameters->getSystem(system);
+               if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite )
+               {
+                       eDVBFrontendParametersSatellite sat;
+                       it->second.m_frontendParameters->getDVBS(sat);
+                       if ((unsigned int)sat.orbital_position != orbpos)
+                               remove=false;
+               }
+               if ( remove && chid.dvbnamespace != eNs && chid.dvbnamespace != ch.dvbnamespace )
+                       remove=false;
+               if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
+                       remove=false;
+               if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
+                       remove=false;
+               if ( remove )
+                       removed_chids.insert(it->first);
+               ++it;
+       }
+       if (!removed_chids.empty())
+       {
+               std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+               while(service != m_services.end())
+               {
+                       eDVBChannelID chid;
+                       service->first.getChannelID(chid);
+                       std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
+                       if (it != removed_chids.end())
+                               service->second->m_flags &= ~flagmask;
+                       ++service;
+               }
+       }
+       return 0;
+}
+
 RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
 {
        channel ch;
@@ -665,7 +853,14 @@ RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontend
 
 RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
 {
-       m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
+       std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(serviceref));
+       if (it == m_services.end())
+       {
+               service->m_flags |= eDVBService::dxNewFound;
+               m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
+       }
+       else
+               it->second->m_flags &= ~eDVBService::dxNewFound;
        return 0;
 }
 
@@ -740,6 +935,22 @@ RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q
        return 0;
 }
 
+eServiceReference eDVBDB::searchReference(int tsid, int onid, int sid)
+{
+       eServiceID Sid(sid);
+       eTransportStreamID Tsid(tsid);
+       eOriginalNetworkID Onid(onid);
+       for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
+               sit != m_services.end(); ++sit)
+       {
+               if (sit->first.getTransportStreamID() == Tsid &&
+                       sit->first.getOriginalNetworkID() == Onid &&
+                       sit->first.getServiceID() == Sid)
+                       return sit->first;
+       }
+       return eServiceReference();
+}
+
 DEFINE_REF(eDVBDBQueryBase);
 
 eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
@@ -886,8 +1097,8 @@ eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference
                                eServiceReferenceDVB ref;
                                ref.setDVBNamespace(dvbnamespace);
                                ref.flags=eServiceReference::flagDirectory;
-                               char buf[64];
-                               snprintf(buf, 64, "(satellitePosition == %d) && ", dvbnamespace>>16);
+                               char buf[128];
+                               snprintf(buf, 128, "(satellitePosition == %d) && ", dvbnamespace>>16);
 
                                ref.path=buf+source.path;
                                unsigned int pos=ref.path.find("FROM");
@@ -900,6 +1111,14 @@ eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference
                                pos=ref.path.find("FROM");
                                ref.path.erase(pos+5);
                                ref.path+="PROVIDERS ORDER BY name";
+//                             eDebug("ref.path now %s", ref.path.c_str());
+                               m_list.push_back(ref);
+
+                               snprintf(buf, 128, "(satellitePosition == %d) && (flags == %d) && ", dvbnamespace>>16, eDVBService::dxNewFound);
+                               ref.path=buf+source.path;
+                               pos=ref.path.find("FROM");
+                               ref.path.erase(pos);
+                               ref.path+="ORDER BY name";
 //                             eDebug("ref.path now %s", ref.path.c_str());
                                m_list.push_back(ref);
                        }
@@ -964,6 +1183,8 @@ static int decodeType(const std::string &type)
                return eDVBChannelQuery::tSatellitePosition;
        else if (type == "channelID")
                return eDVBChannelQuery::tChannelID;
+       else if (type == "flags")
+               return eDVBChannelQuery::tFlags;
        else
                return -1;
 }
@@ -972,6 +1193,13 @@ static int decodeType(const std::string &type)
 RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
 {
        std::list<std::string>::const_iterator end_of_exp;
+       
+       if (begin == end)
+       {
+               eDebug("empty expression!");
+               return 0;
+       }
+       
        if (*begin == "(")
        {
                end_of_exp = begin;
@@ -1188,6 +1416,14 @@ RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
                /* now we recursivly parse that. */
        int r = parseExpression(res, tokens.begin(), tokens.end());
        
+               /* we have an empty (but valid!) expression */
+       if (!r && !res)
+       {
+               res = new eDVBChannelQuery();
+               res->m_inverse = 0;
+               res->m_type = eDVBChannelQuery::tAny;
+       }
+       
        if (res)
        {
                res->m_sort = sort;