const PolyphaseFilter *MakePolyphaseFilter( int iUpFactor, float fCutoffFrequency )
	{
		PolyphaseFiltersLock.Lock();
		pair<int,float> params( make_pair(iUpFactor, fCutoffFrequency) );
		FilterMap::const_iterator it = g_mapPolyphaseFilters.find(params);
		if( it != g_mapPolyphaseFilters.end() )
		{
			/* We already have a filter for this upsampling factor and cutoff; use it. */
			PolyphaseFilter *pPolyphase = it->second;
			PolyphaseFiltersLock.Unlock();
			return pPolyphase;
		}
		int iWinSize = L*iUpFactor;
		float *pFIR = new float[iWinSize];
		GenerateSincLowPassFilter( pFIR, iWinSize, fCutoffFrequency );
		ApplyKaiserWindow( pFIR, iWinSize, 8 );
		NormalizeVector( pFIR, iWinSize );
		MultiplyVector( &pFIR[0], &pFIR[iWinSize], (float) iUpFactor );

		PolyphaseFilter *pPolyphase = new PolyphaseFilter( iUpFactor );
		pPolyphase->Generate( pFIR );
		delete [] pFIR;

		g_mapPolyphaseFilters[params] = pPolyphase;
		PolyphaseFiltersLock.Unlock();
		return pPolyphase;
	}
	const PolyphaseFilter *FindNearestPolyphaseFilter( int iUpFactor, float fCutoffFrequency )
	{
		/* Find a cached filter with the same iUpFactor and a nearby cutoff frequency.
		 * Round the cutoff down, if possible; it's better to filter out too much than
		 * too little. */
		PolyphaseFiltersLock.Lock();
		pair<int,float> params( make_pair(iUpFactor, fCutoffFrequency + 0.0001f) );
		FilterMap::const_iterator it = g_mapPolyphaseFilters.upper_bound( params );
		if( it != g_mapPolyphaseFilters.begin() )
			--it;
		ASSERT( it->first.first == iUpFactor );
		PolyphaseFilter *pPolyphase = it->second;
		PolyphaseFiltersLock.Unlock();
		return pPolyphase;
	}
Пример #3
0
 // Just checks whether style can be created without constructing actual style.
 void check(const std::vector<Tag>& tags, const FilterMap& filters)
 {
     FilterMap::const_iterator iter = filters.find(levelOfDetails_);
     if (iter != filters.end()) {
         for (const Filter& filter : iter->second) {
             bool isMatched = true;
             for (auto it = filter.conditions.cbegin(); it != filter.conditions.cend() && isMatched; ++it) {
                 isMatched &= match_tags(tags.cbegin(), tags.cend(), *it);
             }
             if (isMatched) {
                 canBuild_ = true;
                 return;
             }
         }
     }
 }
Пример #4
0
 // Builds style object. More expensive to call than check.
 void build(const std::vector<Tag>& tags, const FilterMap& filters)
 {
     FilterMap::const_iterator iter = filters.find(levelOfDetails_);
     if (iter != filters.end()) {
         for (const Filter &filter : iter->second) {
             bool isMatched = true;
             for (auto it = filter.conditions.cbegin(); it != filter.conditions.cend() && isMatched; ++it) {
                 isMatched &= match_tags(tags.cbegin(), tags.cend(), *it);
             }
             // merge declarations to style
             if (isMatched) {
                 canBuild_ = true;
                 for (const auto &d : filter.declarations) {
                     style_.put(d.second);
                 }
             }
         }
     }
 }
namespace PolyphaseFilterCache
{
	/* Cache filter data, and reuse it without copying.  All operations after creation
	 * are const, so this doesn't cause thread-safety problems. */
	typedef map<pair<int,float>, PolyphaseFilter *> FilterMap;
	static RageMutex PolyphaseFiltersLock("PolyphaseFiltersLock");
	static FilterMap g_mapPolyphaseFilters;
		
	const PolyphaseFilter *MakePolyphaseFilter( int iUpFactor, float fCutoffFrequency )
	{
		PolyphaseFiltersLock.Lock();
		pair<int,float> params( make_pair(iUpFactor, fCutoffFrequency) );
		FilterMap::const_iterator it = g_mapPolyphaseFilters.find(params);
		if( it != g_mapPolyphaseFilters.end() )
		{
			/* We already have a filter for this upsampling factor and cutoff; use it. */
			PolyphaseFilter *pPolyphase = it->second;
			PolyphaseFiltersLock.Unlock();
			return pPolyphase;
		}
		int iWinSize = L*iUpFactor;
		float *pFIR = new float[iWinSize];
		GenerateSincLowPassFilter( pFIR, iWinSize, fCutoffFrequency );
		ApplyKaiserWindow( pFIR, iWinSize, 8 );
		NormalizeVector( pFIR, iWinSize );
		MultiplyVector( &pFIR[0], &pFIR[iWinSize], (float) iUpFactor );

		PolyphaseFilter *pPolyphase = new PolyphaseFilter( iUpFactor );
		pPolyphase->Generate( pFIR );
		delete [] pFIR;

		g_mapPolyphaseFilters[params] = pPolyphase;
		PolyphaseFiltersLock.Unlock();
		return pPolyphase;
	}

	const PolyphaseFilter *FindNearestPolyphaseFilter( int iUpFactor, float fCutoffFrequency )
	{
		/* Find a cached filter with the same iUpFactor and a nearby cutoff frequency.
		 * Round the cutoff down, if possible; it's better to filter out too much than
		 * too little. */
		PolyphaseFiltersLock.Lock();
		pair<int,float> params( make_pair(iUpFactor, fCutoffFrequency + 0.0001f) );
		FilterMap::const_iterator it = g_mapPolyphaseFilters.upper_bound( params );
		if( it != g_mapPolyphaseFilters.begin() )
			--it;
		ASSERT( it->first.first == iUpFactor );
		PolyphaseFilter *pPolyphase = it->second;
		PolyphaseFiltersLock.Unlock();
		return pPolyphase;
	}
}
Пример #6
0
bool CDSObject::FilterContains(const FilterMap &filter, const QString& name) const
{
    // ContentDirectory Service, 2013 UPnP Forum
    // 2.3.18 A_ARG_TYPE_Filter

    // Exact match
    if (filter.contains(name, Qt::CaseInsensitive))
        return true;

    // # signfies that this property and all it's children must be returned
    // This is presently implemented higher up to save time

    // If an attribute is required then it's parent must also be returned
    QString dependentAttribute = QString("%1@").arg(name);
    QStringList matches = filter.filter(name, Qt::CaseInsensitive);
    QStringList::iterator it;
    for (it = matches.begin(); it != matches.end(); ++it)
    {
        if ((*it).startsWith(dependentAttribute))
            return true;
    }

    return false;
}
Пример #7
0
void CDSObject::toXml( QTextStream &os, FilterMap &filter,
                       bool ignoreChildren ) const
{
    QString sEndTag = "";

    /**
     * NOTE FilterMap contains a list of what should be included, not what should
     *      be excluded.
     *
     *      The client is expected either to indicate that everything should be
     *      returned with an asterix, or to supply a comma seperated list of
     *      the only the named properties and attributes.
     *
     *      @ - Attributes are denoted by format <element>@<attribute>
     *
     *      # - The use of a hash at the end of a name indicates that this
     *          property and all it's children and attributes should be returned.
     *
     *      Inclusion of an attribute in the filter list implies the inclusion
     *      of it's parent element and value.
     *      e.g. filter="res@size" implies <res size="{size}">{url}</res>
     *      However optional tags such as res@duration which are not named will
     *      be omitted.
     *
     *      'Required' properties must always be included irrespective of
     *      any filter!
     *
     *      See UPnP MediaServer, ContentDirectory Service Section 2.3.18, 2013
     */
    bool    bFilter = true;

    if (filter.contains("*"))
        bFilter = false;

    switch( m_eType )
    {   
        case OT_Container:
        {
            if (bFilter && filter.contains("container#"))
                bFilter = false;

            os << "<container id=\"" << m_sId
               << "\" parentID=\"" << m_sParentId
               << "\" restricted=\"" << GetBool( m_bRestricted );

            if (!bFilter || filter.contains("@searchable"))
                os << "\" searchable=\"" << GetBool( m_bSearchable );

            if (!bFilter || filter.contains("@childCount"))
                os << "\" childCount=\"" << GetChildCount();

            if (!bFilter || filter.contains("@childContainerCount"))
                os << "\" childContainerCount=\"" << GetChildContainerCount();

               os << "\" >" << endl;

            sEndTag = "</container>";

            break;
        }
        case OT_Item:
        {
            if (bFilter && filter.contains("item#"))
                bFilter = false;

            os << "<item id=\"" << m_sId
               << "\" parentID=\"" << m_sParentId
               << "\" restricted=\"" << GetBool( m_bRestricted )
               << "\" >" << endl;

            sEndTag = "</item>";

            break;
        }
        default: break;
    }

    os << "<dc:title>"   << m_sTitle << "</dc:title>" << endl;
    os << "<upnp:class>" << m_sClass << "</upnp:class>" << endl;

    // ----------------------------------------------------------------------
    // Output all Properties
    // ----------------------------------------------------------------------

    Properties::const_iterator it = m_properties.begin();
    for (; it != m_properties.end(); ++it)
    {
        const Property *pProp = *it;

        if (pProp->m_bRequired || (!pProp->GetValue().isEmpty()))
        {
            QString sName;
            
            if (!pProp->m_sNameSpace.isEmpty())
                sName = pProp->m_sNameSpace + ':' + pProp->m_sName;
            else
                sName = pProp->m_sName;

            if (pProp->m_bRequired ||
                (!bFilter) ||
                FilterContains(filter, sName))
            {
                bool filterAttributes = true;
                if (!bFilter || filter.contains(QString("%1#").arg(sName)))
                    filterAttributes = false;

                os << "<"  << sName;

                NameValues::const_iterator nit = pProp->m_lstAttributes.begin();
                for (; nit != pProp->m_lstAttributes.end(); ++ nit)
                {
                    QString filterName = QString("%1@%2").arg(sName)
                                                         .arg((*nit).m_sName);
                    if ((*nit).m_bRequired  || !filterAttributes ||
                        filter.contains(filterName))
                        os << " " << (*nit).m_sName << "=\"" << (*nit).m_sValue << "\"";
                }

                os << ">";
                os << pProp->GetEncodedValue();
                os << "</" << sName << ">" << endl;
            }
        }
    }

    // ----------------------------------------------------------------------
    // Output any Res Elements
    // ----------------------------------------------------------------------

    if (!bFilter || filter.contains("res"))
    {
        bool filterAttributes = true;
        if (!bFilter || filter.contains("res#"))
            filterAttributes = false;
        Resources::const_iterator rit = m_resources.begin();
        for (; rit != m_resources.end(); ++rit)
        {
            os << "<res protocolInfo=\"" << (*rit)->m_sProtocolInfo << "\" ";

            QString filterName;
            NameValues::const_iterator nit = (*rit)->m_lstAttributes.begin();
            for (; nit != (*rit)->m_lstAttributes.end(); ++ nit)
            {
                filterName = QString("res@%1").arg((*nit).m_sName);
                if ((*nit).m_bRequired  || !filterAttributes ||
                    filter.contains(filterName))
                    os << (*nit).m_sName << "=\"" << (*nit).m_sValue << "\" ";
            }

            os << ">" << (*rit)->m_sURI;
            os << "</res>" << endl;
        }
    }

    // ----------------------------------------------------------------------
    // Output any children
    // ----------------------------------------------------------------------

    if (!ignoreChildren)
    {
        CDSObjects::const_iterator cit = m_children.begin();
        for (; cit != m_children.end(); ++cit)
            (*cit)->toXml(os, filter);
    }

    // ----------------------------------------------------------------------
    // Close Element Tag
    // ----------------------------------------------------------------------

    os << sEndTag << endl;
    os << flush;
}
Пример #8
0
void CDSObject::toXml(QTextStream &os, FilterMap &filter) const
{
    QString sEndTag = "";
    bool    bFilter = true;

    if (filter.indexOf( "*" ) != -1)
        bFilter = false;

    switch( m_eType )
    {   
        case OT_Container:
        {
            os << "<container id=\"" << m_sId << "\" parentID=\"" << m_sParentId
               << "\" childCount=\"" << GetChildCount() << "\" restricted=\"" << GetBool( m_bRestricted )
               << "\" searchable=\"" << GetBool( m_bSearchable ) << "\" >";

            sEndTag = "</container>";

            break;
        }
        case OT_Item:
        {
            os << "<item id=\"" << m_sId << "\" parentID=\"" << m_sParentId
               << "\" restricted=\"" << GetBool( m_bRestricted ) << "\" >";

            sEndTag = "</item>";

            break;
        }
        default: break;
    }

    os << "<dc:title>"   << m_sTitle << "</dc:title>";
    os << "<upnp:class>" << m_sClass << "</upnp:class>";

    // ----------------------------------------------------------------------
    // Output all Properties
    // ----------------------------------------------------------------------

    Properties::const_iterator it = m_properties.begin();
    for (; it != m_properties.end(); ++it)
    {
        const Property *pProp = *it;

        if (pProp->m_bRequired || (pProp->m_sValue.length() > 0))
        {
            QString sName;
            
            if (pProp->m_sNameSpace.length() > 0)
                sName = pProp->m_sNameSpace + ':' + pProp->m_sName;
            else
                sName = pProp->m_sName;

            if (pProp->m_bRequired || !bFilter 
                || ( filter.indexOf( sName ) != -1))
            {
                os << "<"  << sName;

                    NameValues::const_iterator nit = pProp->m_lstAttributes.begin();
                    for (; nit != pProp->m_lstAttributes.end(); ++ nit)
                        os << " " <<(*nit).sName << "=\"" << (*nit).sValue << "\"";

                os << ">";
                os << pProp->m_sValue;
                os << "</" << sName << ">";
            }
        }
    }

    // ----------------------------------------------------------------------
    // Output any Res Elements
    // ----------------------------------------------------------------------

    Resources::const_iterator rit = m_resources.begin();
    for (; rit != m_resources.end(); ++rit)
    {
        os << "<res protocolInfo=\"" << (*rit)->m_sProtocolInfo << "\" ";

        NameValues::const_iterator nit = (*rit)->m_lstAttributes.begin();
        for (; nit != (*rit)->m_lstAttributes.end(); ++ nit)
            os << (*nit).sName << "=\"" << (*nit).sValue << "\" ";

        os << ">" << (*rit)->m_sURI;
        os << "</res>\r\n";
    }

    // ----------------------------------------------------------------------
    // Output any children
    // ----------------------------------------------------------------------

    CDSObjects::const_iterator cit = m_children.begin();
    for (; cit != m_children.end(); ++cit)
        (*cit)->toXml(os, filter);

    // ----------------------------------------------------------------------
    // Close Element Tag
    // ----------------------------------------------------------------------

    os << sEndTag;
    os << flush;
}