Exemplo n.º 1
0
void UPnpCDSMusic::AddItem( const UPnpCDSRequest    *pRequest, 
                            const QString           &sObjectId,
                            UPnpCDSExtensionResults *pResults,
                            bool                     bAddRef,
                            MSqlQuery               &query )
{
    QString        sName;

    int            nId          = query.value( 0).toInt();
    QString        sArtist      = query.value( 1).toString();
    QString        sAlbum       = query.value( 2).toString();
    QString        sTitle       = query.value( 3).toString();
    QString        sGenre       = query.value( 4).toString();
//    int            nYear        = query.value( 5).toInt();
    int            nTrackNum    = query.value( 6).toInt();
    QString        sDescription = query.value( 7).toString();
    QString        sFileName    = query.value( 8).toString();
    uint           nLength      = query.value( 9).toInt();

/*
    if ((nNodeIdx == 0) || (nNodeIdx == 1))
    {
        sName = QString( "%1-%2:%3" )
                   .arg( sArtist)
                   .arg( sAlbum )
                   .arg( sTitle );
    }
    else
*/
        sName = sTitle;

//cout << nId << " " << sName << endl;


    // ----------------------------------------------------------------------
    // Cache Host ip Address & Port
    // ----------------------------------------------------------------------

//    if (!m_mapBackendIp.contains( sHostName ))
//        m_mapBackendIp[ sHostName ] = gCoreContext->GetSettingOnHost( "BackendServerIp", sHostName);
//
//    if (!m_mapBackendPort.contains( sHostName ))
//        m_mapBackendPort[ sHostName ] = gCoreContext->GetSettingOnHost("BackendStatusPort", sHostName);

    QString sServerIp = gCoreContext->GetSetting( "BackendServerIp"   );
    QString sPort     = gCoreContext->GetSetting( "BackendStatusPort" );

    // ----------------------------------------------------------------------
    // Build Support Strings
    // ----------------------------------------------------------------------

    QString sURIBase   = QString( "http://%1:%2/Myth/" )
                            .arg( sServerIp )
                            .arg( sPort     );

    QString sURIParams = QString( "?Id=%1" )
                            .arg( nId );


    QString sId        = QString( "Music/1/item%1")
                            .arg( sURIParams );

    CDSObject *pItem   = CDSObject::CreateMusicTrack( sId,
                                                      sName,
                                                      sObjectId );
    pItem->m_bRestricted  = true;
    pItem->m_bSearchable  = true;
    pItem->m_sWriteStatus = "NOT_WRITABLE";

    if ( bAddRef )
    {
        QString sRefId = QString( "%1/0/item%2")
                            .arg( m_sExtensionId )
                            .arg( sURIParams     );

        pItem->SetPropValue( "refID", sRefId );
    }

    pItem->SetPropValue( "genre"                , sGenre      );
    pItem->SetPropValue( "description"          , sTitle      );
    pItem->SetPropValue( "longDescription"      , sDescription);

    pItem->SetPropValue( "artist"               ,  sArtist    );
    pItem->SetPropValue( "album"                ,  sAlbum     );
    pItem->SetPropValue( "originalTrackNumber"  ,  QString::number( nTrackNum  ));

/*

    pObject->AddProperty( new Property( "publisher"       , "dc"   ));
    pObject->AddProperty( new Property( "language"        , "dc"   ));
    pObject->AddProperty( new Property( "relation"        , "dc"   ));
    pObject->AddProperty( new Property( "rights"          , "dc"   ));


    pObject->AddProperty( new Property( "playlist"            , "upnp" ));
    pObject->AddProperty( new Property( "storageMedium"       , "upnp" ));
    pObject->AddProperty( new Property( "contributor"         , "dc"   ));
    pObject->AddProperty( new Property( "date"                , "dc"   ));

*/


    pResults->Add( pItem );

    // ----------------------------------------------------------------------
    // Add Music Resource Element based on File extension (HTTP)
    // ----------------------------------------------------------------------

    QFileInfo fInfo( sFileName );

    QString sMimeType = HTTPRequest::GetMimeType( fInfo.suffix() );
    QString sProtocol = QString( "http-get:*:%1:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000" ).arg( sMimeType  );
    QString sURI      = QString( "%1GetMusic%2").arg( sURIBase   )
                                                .arg( sURIParams );

    Resource *pRes = pItem->AddResource( sProtocol, sURI );

    nLength /= 1000;

    QString sDur;

    sDur.sprintf("%02d:%02d:%02d",
                  (nLength / 3600) % 24,
                  (nLength / 60) % 60,
                  nLength % 60);

    pRes->AddAttribute( "duration"  , sDur      );
}
Exemplo n.º 2
0
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessKey( UPnpCDSRequest          *pRequest,
                                                       UPnpCDSExtensionResults *pResults, 
                                                       QStringList             &idPath )
{
    pResults->m_nTotalMatches   = 0;
    pResults->m_nUpdateID       = 1;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------
    
    QString sKey = idPath.last().section( '=', 1, 1 );
    sKey = QUrl::fromPercentEncoding(sKey.toUtf8());

    if (sKey.length() > 0)
    {
        int nNodeIdx = idPath[ idPath.count() - 2 ].toInt();

        switch( pRequest->m_eBrowseFlag )
        { 

            case CDS_BrowseMetadata:
            {                              
                UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx );

                if (pInfo == NULL)
                    return pResults;

                pRequest->m_sParentId = RemoveToken( "/", pRequest->m_sObjectId, 1 );

                // --------------------------------------------------------------
                // Since Key is not always the title, we need to lookup title.
                // --------------------------------------------------------------

                MSqlQuery query(MSqlQuery::InitCon());

                if (query.isConnected())
                {
                    QString sSQL   = QString( pInfo->sql )
                                        .arg( pInfo->where );

                    // -=>TODO: There is a problem when called for an Item, instead of a container
                    //          sKey = '<KeyName>/item?ChanId' which is incorrect.


                    query.prepare  ( sSQL );
                    query.bindValue( ":KEY", sKey );

                    if (query.exec() && query.next())
                    {
                        // ----------------------------------------------
                        // Return Container Object Only
                        // ----------------------------------------------

                        pResults->m_nTotalMatches   = 1;
                        pResults->m_nUpdateID       = 1;

                        CDSObject *pItem = CreateContainer( pRequest->m_sObjectId,
                                                            query.value(1).toString(),
                                                            pRequest->m_sParentId );

                        pItem->SetChildCount( GetDistinctCount( pInfo ));

                        pResults->Add( pItem );
                    }
                }
                break;
            }

            case CDS_BrowseDirectChildren:
            {
        
                CreateItems( pRequest, pResults, nNodeIdx, sKey, true );

                break;
            }

            case CDS_BrowseUnknown:
                default:
                break;
        }
    }

    return pResults;                                                                           
}
Exemplo n.º 3
0
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessRoot( UPnpCDSRequest          *pRequest, 
                                                        UPnpCDSExtensionResults *pResults, 
                                                        QStringList             &/*idPath*/ )
{
    pResults->m_nTotalMatches   = 0;
    pResults->m_nUpdateID       = 1;

    short nRootCount = GetRootCount();

    switch( pRequest->m_eBrowseFlag )
    { 
        case CDS_BrowseMetadata:
        {
            // --------------------------------------------------------------
            // Return Root Object Only
            // --------------------------------------------------------------

            pResults->m_nTotalMatches   = 1;
            pResults->m_nUpdateID       = 1;

            CDSObject *pRoot = CreateContainer( m_sExtensionId, m_sName, "0");

            pRoot->SetChildCount( nRootCount );

            pResults->Add( pRoot ); 

            break;
        }

        case CDS_BrowseDirectChildren:
        {
        VERBOSE(VB_UPNP, "CDS_BrowseDirectChildren");
            pResults->m_nUpdateID     = 1;
            pResults->m_nTotalMatches = nRootCount ;
            
            if ( pRequest->m_nRequestedCount == 0)
                pRequest->m_nRequestedCount = nRootCount ;

            short nStart = Max( pRequest->m_nStartingIndex, short( 0 ));
            short nEnd   = Min( nRootCount, short( nStart + pRequest->m_nRequestedCount));

            if (nStart < nRootCount)
            {
                for (short nIdx = nStart; nIdx < nEnd; nIdx++)
                {
                    UPnpCDSRootInfo *pInfo = GetRootInfo( nIdx );
                    if (pInfo != NULL)
                    {

                        QString sId = QString( "%1/%2" ).arg( pRequest->m_sObjectId   )
                                                        .arg( nIdx );

                        CDSObject *pItem = CreateContainer( sId,  
                                                            QObject::tr( pInfo->title ), 
                                                            m_sExtensionId );

                        pItem->SetChildCount( GetDistinctCount( pInfo ) );

                        pResults->Add( pItem );
                    }
                }
            }
        }

        case CDS_BrowseUnknown:
        default:
            break;
    }

    return pResults;
}
Exemplo n.º 4
0
UPnpCDSExtensionResults *UPnpCDSExtension::ProcessContainer( UPnpCDSRequest          *pRequest,
                                                             UPnpCDSExtensionResults *pResults,
                                                             int                      nNodeIdx,
                                                             QStringList             &/*idPath*/ )

{
    pResults->m_nUpdateID     = 1;
    pResults->m_nTotalMatches = 0;

    UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx );

    if (pInfo == NULL)
        return pResults;

    switch( pRequest->m_eBrowseFlag )
    { 
        case CDS_BrowseMetadata:
        {
            // --------------------------------------------------------------
            // Return Container Object Only
            // --------------------------------------------------------------

            pResults->m_nTotalMatches   = 1;
            pResults->m_nUpdateID       = 1;

            CDSObject *pItem = CreateContainer( pRequest->m_sObjectId,  
                                                QObject::tr( pInfo->title ), 
                                                m_sExtensionId );

            pItem->SetChildCount( GetDistinctCount( pInfo ));

            pResults->Add( pItem ); 

            break;
        }

        case CDS_BrowseDirectChildren:
        {
            pResults->m_nTotalMatches = GetDistinctCount( pInfo );
            pResults->m_nUpdateID     = 1;

            if (pRequest->m_nRequestedCount == 0) 
                pRequest->m_nRequestedCount = SHRT_MAX;

            MSqlQuery query(MSqlQuery::InitCon());

            if (query.isConnected())
            {
                // Remove where clause placeholder.

                QString sSQL = pInfo->sql;

                sSQL.remove( "%1" );

                sSQL += QString( " LIMIT %2, %3" )
                           .arg( pRequest->m_nStartingIndex  )
                           .arg( pRequest->m_nRequestedCount );

                query.prepare( sSQL );

                if (query.exec())
                {

                    while(query.next())
                    {
                        QString sKey   = query.value(0).toString();
                        QString sTitle = query.value(1).toString();
                        long    nCount = query.value(2).toInt();

                        if (sTitle.length() == 0)
                            sTitle = "(undefined)";

                        QString sId = QString( "%1/key=%2" )
                                         .arg( pRequest->m_sParentId )
                                         .arg( sKey );

                        CDSObject *pRoot = CreateContainer( sId, sTitle, pRequest->m_sParentId );

                        pRoot->SetChildCount( nCount );

                        pResults->Add( pRoot ); 
                    }
                }
            }

            break;
        }

        case CDS_BrowseUnknown:
            break;

    }

    return pResults;
}
Exemplo n.º 5
0
void UPnpCDSMusic::AddItem( const UPnpCDSRequest    *pRequest, 
                            const QString           &sObjectId,
                            UPnpCDSExtensionResults *pResults,
                            bool                     bAddRef,
                            MSqlQuery               &query )
{
    QString        sName;

    int            nId          = query.value( 0).toInt();
    QString        sArtist      = query.value( 1).toString();
    QString        sAlbum       = query.value( 2).toString();
    QString        sTitle       = query.value( 3).toString();
    QString        sGenre       = query.value( 4).toString();
    int            nYear        = query.value( 5).toInt();
    int            nTrackNum    = query.value( 6).toInt();
    QString        sDescription = query.value( 7).toString();
    QString        sFileName    = query.value( 8).toString();
    uint           nLength      = query.value( 9).toInt();
    uint64_t       nFileSize    = (quint64)query.value(10).toULongLong();

#if 0
    if ((nNodeIdx == 0) || (nNodeIdx == 1))
    {
        sName = QString( "%1-%2:%3" )
                   .arg( sArtist)
                   .arg( sAlbum )
                   .arg( sTitle );
    }
    else
#endif
        sName = sTitle;


    // ----------------------------------------------------------------------
    // Cache Host ip Address & Port
    // ----------------------------------------------------------------------

#if 0
    if (!m_mapBackendIp.contains( sHostName ))
        m_mapBackendIp[ sHostName ] = gCoreContext->GetSettingOnHost( "BackendServerIp", sHostName);

    if (!m_mapBackendPort.contains( sHostName ))
        m_mapBackendPort[ sHostName ] = gCoreContext->GetSettingOnHost("BackendStatusPort", sHostName);
#endif

    QString sServerIp = gCoreContext->GetSetting( "BackendServerIp"   );
    QString sPort     = gCoreContext->GetSetting( "BackendStatusPort" );

    // ----------------------------------------------------------------------
    // Build Support Strings
    // ----------------------------------------------------------------------

    QString sURIBase   = QString( "http://%1:%2/Content/" )
                            .arg( sServerIp )
                            .arg( sPort     );

    QString sURIParams = QString( "?Id=%1" )
                            .arg( nId );


    QString sId        = QString( "Music/1/item%1")
                            .arg( sURIParams );

    CDSObject *pItem   = CDSObject::CreateMusicTrack( sId,
                                                      sName,
                                                      sObjectId );
    pItem->m_bRestricted  = true;
    pItem->m_bSearchable  = true;
    pItem->m_sWriteStatus = "NOT_WRITABLE";

    if ( bAddRef )
    {
        QString sRefId = QString( "%1/0/item%2")
                            .arg( m_sExtensionId )
                            .arg( sURIParams     );

        pItem->SetPropValue( "refID", sRefId );
    }

    pItem->SetPropValue( "genre"                , sGenre      );
    pItem->SetPropValue( "description"          , sTitle      );
    pItem->SetPropValue( "longDescription"      , sDescription);

    pItem->SetPropValue( "artist"               ,  sArtist    );
    pItem->SetPropValue( "album"                ,  sAlbum     );
    pItem->SetPropValue( "originalTrackNumber"  ,  QString::number(nTrackNum));
    if (nYear > 0 && nYear < 9999)
        pItem->SetPropValue( "date",  QDate(nYear,1,1).toString(Qt::ISODate));

#if 0
    pObject->AddProperty( new Property( "publisher"       , "dc"   ));
    pObject->AddProperty( new Property( "language"        , "dc"   ));
    pObject->AddProperty( new Property( "relation"        , "dc"   ));
    pObject->AddProperty( new Property( "rights"          , "dc"   ));


    pObject->AddProperty( new Property( "playlist"            , "upnp" ));
    pObject->AddProperty( new Property( "storageMedium"       , "upnp" ));
    pObject->AddProperty( new Property( "contributor"         , "dc"   ));
    pObject->AddProperty( new Property( "date"                , "dc"   ));
#endif

    QString sArtURI = QString( "%1GetAlbumArt?Id=%2").arg( sURIBase   )
                                                     .arg( nId );

    QList<Property*> propList = pItem->GetProperties("albumArtURI");
    if (propList.size() >= 4)
    {
        // Prefer JPEG over PNG here, although PNG is allowed JPEG probably
        // has wider device support and crucially the filesizes are smaller
        // which speeds up loading times over the network

        // We MUST include the thumbnail size, but since some clients may use the
        // first image they see and the thumbnail is tiny, instead return the
        // medium first. The large could be very large, which is no good if the
        // client is pulling images for an entire list at once!

        // Medium
        Property *pProp = propList.at(0);
        if (pProp)
        {
            // Must be no more than 1024x768
            pProp->m_sValue = sArtURI;
            pProp->m_sValue.append("&amp;Width=1024&amp;Height=768");
            pProp->AddAttribute("dlna:profileID", "JPG_MED");
            pProp->AddAttribute("xmlns:dlna", "urn:schemas-dlna-org:metadata-1-0");
        }

        // Thumbnail
        pProp = propList.at(1);
        if (pProp)
        {
            // At least one albumArtURI must be a ThumbNail (TN) no larger
            // than 160x160, and it must also be a jpeg
            pProp->m_sValue = sArtURI;
            pProp->m_sValue.append("&amp;Width=160&amp;Height=160");
            pProp->AddAttribute("dlna:profileID", "JPG_TN");
            pProp->AddAttribute("xmlns:dlna", "urn:schemas-dlna-org:metadata-1-0");
        }

        // Small
        pProp = propList.at(2);
        if (pProp)
        {
            // Must be no more than 640x480
            pProp->m_sValue = sArtURI;
            pProp->m_sValue.append("&amp;Width=640&amp;Height=480");
            pProp->AddAttribute("dlna:profileID", "JPG_SM");
            pProp->AddAttribute("xmlns:dlna", "urn:schemas-dlna-org:metadata-1-0");
        }

        // Large
        pProp = propList.at(3);
        if (pProp)
        {
            // Must be no more than 4096x4096 - for our purposes, just return
            // a fullsize image
            pProp->m_sValue = sArtURI;
            pProp->AddAttribute("dlna:profileID", "JPG_LRG");
            pProp->AddAttribute("xmlns:dlna", "urn:schemas-dlna-org:metadata-1-0");
        }
    }

    pResults->Add( pItem );

    // ----------------------------------------------------------------------
    // Add Music Resource Element based on File extension (HTTP)
    // ----------------------------------------------------------------------

    QFileInfo fInfo( sFileName );

    QString sMimeType = HTTPRequest::GetMimeType( fInfo.suffix() );
    QString sProtocol = QString( "http-get:*:%1:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000" ).arg( sMimeType  );
    QString sURI      = QString( "%1GetMusic%2").arg( sURIBase   )
                                                .arg( sURIParams );

    Resource *pRes = pItem->AddResource( sProtocol, sURI );

    nLength /= 1000;

    QString sDur;

    sDur.sprintf("%02d:%02d:%02d",
                  (nLength / 3600) % 24,
                  (nLength / 60) % 60,
                  nLength % 60);

    pRes->AddAttribute( "duration"  , sDur      );
    if (nFileSize > 0)
        pRes->AddAttribute( "size"      , QString::number( nFileSize) );
}
Exemplo n.º 6
0
void CDSObject::toXml( QTextStream &os ) //, FilterMap &filter )
{
    QString sEndTag = "";
    bool    bFilter = false;

    //  -=>TODO: Need to add Filter Support

//    if (filter.find( "*" ) != filter.end())
//        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
    // ----------------------------------------------------------------------

    for( PropertiesIterator it( m_properties ); it.current(); ++it )
    {
        Property *pProp = it.current();

        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.find( sName ) != filter.end())
            {
                os << "<"  << sName << ">";
                os << pProp->m_sValue;
                os << "</" << sName << ">";
            }
        }
    }

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

    for ( Resource *pRes  = m_resources.first(); 
                    pRes != NULL; 
                    pRes  = m_resources.next() )
    {
        os << "<res protocolInfo=\"" << pRes->m_sProtocolInfo << "\" ";

        for (NameValue *pNV  = pRes->m_lstAttributes.first(); 
                        pNV != NULL; 
                        pNV  = pRes->m_lstAttributes.next())
        {                               
            os << pNV->sName << "=\"" << pNV->sValue << "\" ";
        }

        os << ">" << pRes->m_sURI;                                            
        os << "</res>\r\n";
    }

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

    for ( CDSObject *pObject  = m_children.first(); 
                  pObject != NULL; 
                  pObject = m_children.next() )
    {
        pObject->toXml( os ); //, filter );
    }

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

    os << sEndTag;
}