示例#1
0
文件: dbutil.cpp 项目: mdda/mythtv
/** \fn DBUtil::CheckRepairStatus(MSqlQuery &query)
 *  \brief Parse the results of a CHECK TABLE or REPAIR TABLE run.
 *
 *   This function reads the records returned by a CHECK TABLE or REPAIR TABLE
 *   run and determines the status of the table(s). The query should have
 *   columns Table, Msg_type, and Msg_text.
 *
 *   The function properly handles multiple records for a single table. If the
 *   last record for a given table shows a status (Msg_type) of OK (Msg_text),
 *   the table is considered OK, even if an error or warning appeared before
 *   (this could be the case, for example, when an empty table is crashed).
 *
 *  \param query An already-executed CHECK TABLE or REPAIR TABLE query whose
 *               results should be parsed.
 *  \return A list of names of not-OK (errored or crashed) tables
 *  \sa DBUtil::CheckTables(const bool, const QString)
 *  \sa DBUtil::RepairTables(const QStringList)
 */
QStringList DBUtil::CheckRepairStatus(MSqlQuery &query)
{
    QStringList tables;
    QSqlRecord record = query.record();
    int table_index = record.indexOf("Table");
    int type_index = record.indexOf("Msg_type");
    int text_index = record.indexOf("Msg_text");
    QString table, type, text, previous_table;
    bool ok = true;
    while (query.next())
    {
        table = query.value(table_index).toString();
        type = query.value(type_index).toString();
        text = query.value(text_index).toString();
        if (table != previous_table)
        {
            if (!ok)
            {
                tables.append(previous_table);
                ok = true;
            }
            previous_table = table;
        }
        // If the final row shows status OK, the table is now good
        if ("status" == type.toLower() && "ok" == text.toLower())
            ok = true;
        else if ("error" == type.toLower() ||
                 ("status" == type.toLower() && "ok" != text.toLower()))
            ok = false;
    }
    // Check the last table in the list
    if (!ok)
        tables.append(table);
    return tables;
}
示例#2
0
static void fill_settings(
    MythSettingList &settings, MSqlQuery &query, MythSetting::SettingType stype)
{
    QMap<QString,QString> map;
    while (query.next())
        map[query.value(0).toString()] = query.value(1).toString();

    MythSettingList::const_iterator it = settings.begin();
    for (; it != settings.end(); ++it)
        fill_setting(*it, map, stype);
}
示例#3
0
/** \fn     ImageUtils::LoadDirectoryValues(MSqlQuery &, ImageMetadata *)
 *  \brief  Loads the directory information from the database into the dataMap
 *  \param  query Information from the database
 *  \param  dm Holds the loaded information
 *  \return void
 */
void ImageUtils::LoadDirectoryValues(MSqlQuery &query, ImageMetadata *dm)
{
    dm->m_id            = query.value(0).toInt();
    dm->m_fileName      = query.value(1).toString();
    dm->m_name          = query.value(2).toString();
    dm->m_path          = query.value(3).toString();
    dm->m_parentId      = query.value(4).toInt();
    dm->m_dirCount      = query.value(5).toInt();
    dm->m_fileCount     = query.value(6).toInt();
    dm->m_isHidden      = query.value(7).toInt();

    // preset all directories as subfolders
    dm->m_type          = kSubDirectory;
}
示例#4
0
/** \fn     GalleryDatabaseHelper::LoadDirectoryValues(MSqlQuery &, ImageMetadata *)
 *  \brief  Loads the directory information from the database
 *  \param  query Information from the database
 *  \param  im Holds the loaded information
 *  \return void
 */
void GalleryDatabaseHelper::LoadDirectoryValues(MSqlQuery &query, ImageMetadata *im)
{
    im->m_id            = query.value(0).toInt();
    im->m_fileName      = query.value(1).toString();
    im->m_name          = query.value(2).toString();
    im->m_path          = query.value(3).toString();
    im->m_parentId      = query.value(4).toInt();
    im->m_dirCount      = query.value(5).toInt();
    im->m_fileCount     = query.value(6).toInt();
    im->m_isHidden      = query.value(7).toInt();

    // preset all directories as subfolders
    im->m_type          = kSubDirectory;

    LoadDirectoryThumbnailValues(im);
}
示例#5
0
bool ProgramData::DeleteOverlaps(
    MSqlQuery &query, uint chanid, const ProgInfo &pi)
{
    if (VERBOSE_LEVEL_CHECK(VB_XMLTV, LOG_INFO))
    {
        // Get overlaps..
        query.prepare(
            "SELECT title,starttime,endtime "
            "FROM program "
            "WHERE chanid     = :CHANID AND "
            "      starttime >= :START AND "
            "      starttime <  :END;");
        query.bindValue(":CHANID", chanid);
        query.bindValue(":START",  pi.starttime);
        query.bindValue(":END",    pi.endtime);

        if (!query.exec())
            return false;

        if (!query.next())
            return true;

        do
        {
            LOG(VB_XMLTV, LOG_INFO,
                QString("Removing existing program: %1 - %2 %3 %4")
                    .arg(query.value(1).toDateTime().toString(Qt::ISODate))
                    .arg(query.value(2).toDateTime().toString(Qt::ISODate))
                    .arg(pi.channel)
                    .arg(query.value(0).toString()));
        } while (query.next());
    }

    if (!ClearDataByChannel(chanid, pi.starttime, pi.endtime, false))
    {
        LOG(VB_XMLTV, LOG_ERR,
            QString("Program delete failed    : %1 - %2 %3 %4")
                .arg(pi.starttime.toString(Qt::ISODate))
                .arg(pi.endtime.toString(Qt::ISODate))
                .arg(pi.channel)
                .arg(pi.title));
        return false;
    }

    return true;
}
示例#6
0
/** \fn     ImageUtils::LoadFileValues(MSqlQuery &, ImageMetadata *)
 *  \brief  Loads the file information from the database into the dataMap
 *  \param  query Information from the database
 *  \param  dm Holds the loaded information
 *  \return void
 */
void ImageUtils::LoadFileValues(MSqlQuery &query, ImageMetadata *dm)
{
    dm->m_id            = query.value(0).toInt();
    dm->m_fileName      = query.value(1).toString();
    dm->m_name          = query.value(2).toString();
    dm->m_path          = query.value(3).toString();
    dm->m_parentId      = query.value(4).toInt();
    dm->m_type          = query.value(5).toInt();
    dm->m_modTime       = query.value(6).toInt();
    dm->m_size          = query.value(7).toInt();
    dm->m_extension     = query.value(8).toString();
    dm->SetAngle(         query.value(9).toInt());
    dm->m_date          = query.value(10).toInt();
    dm->SetZoom(          query.value(11).toInt());
    dm->m_isHidden      = query.value(12).toInt();
    dm->SetOrientation(   query.value(13).toInt(), true);
}
示例#7
0
/** \fn     GalleryDatabaseHelper::LoadFileValues(MSqlQuery &, ImageMetadata *)
 *  \brief  Loads the file information from the database
 *  \param  query Information from the database
 *  \param  im Holds the loaded information
 *  \return void
 */
void GalleryDatabaseHelper::LoadFileValues(MSqlQuery &query, ImageMetadata *im)
{
    im->m_id            = query.value(0).toInt();
    im->m_fileName      = query.value(1).toString();
    im->m_name          = query.value(2).toString();
    im->m_path          = query.value(3).toString();
    im->m_parentId      = query.value(4).toInt();
    im->m_type          = query.value(5).toInt();
    im->m_modTime       = query.value(6).toInt();
    im->m_size          = query.value(7).toInt();
    im->m_extension     = query.value(8).toString();
    im->SetAngle(         query.value(9).toInt());
    im->m_date          = query.value(10).toInt();
    im->SetZoom(          query.value(11).toInt());
    im->m_isHidden      = query.value(12).toInt();
    im->SetOrientation(   query.value(13).toInt(), true);

    LoadFileThumbnailValues(im);
}
示例#8
0
uint DBPerson::GetPersonDB(MSqlQuery &query) const
{
    query.prepare(
        "SELECT person "
        "FROM people "
        "WHERE name = :NAME");
    query.bindValue(":NAME", name);

    if (!query.exec())
        MythDB::DBError("get_person", query);
    else if (query.next())
        return query.value(0).toUInt();

    return 0;
}
示例#9
0
void UPnpCDSTv::AddItem( const UPnpCDSRequest    *pRequest, 
                         const QString           &sObjectId,
                         UPnpCDSExtensionResults *pResults,
                         bool                     bAddRef,
                         MSqlQuery               &query )
{
    int            nChanid      = query.value( 0).toInt();
    QDateTime      dtStartTime  = query.value( 1).toDateTime();
    QDateTime      dtEndTime    = query.value( 2).toDateTime();
    QString        sTitle       = query.value( 3).toString();
    QString        sSubtitle    = query.value( 4).toString();
    QString        sDescription = query.value( 5).toString();
    QString        sCategory    = query.value( 6).toString();
    QString        sHostName    = query.value( 7).toString();
    QString        sRecGroup    = query.value( 8).toString();
    uint64_t       nFileSize    = query.value( 9).toULongLong();
    QString        sBaseName    = query.value(10).toString();

    QDateTime      dtProgStart  = query.value(11).toDateTime();
    QDateTime      dtProgEnd    = query.value(12).toDateTime();
    QString        sStorageGrp  = query.value(13).toString();

    // ----------------------------------------------------------------------
    // 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);

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

    QString sName      = sTitle + ": " + (sSubtitle.isEmpty() ? sDescription : sSubtitle);

    QString sURIBase   = QString( "http://%1:%2/Myth/" )
                            .arg( m_mapBackendIp  [ sHostName ] )
                            .arg( m_mapBackendPort[ sHostName ] );

    QString sURIParams = QString( "?ChanId=%1&amp;StartTime=%2" )
                            .arg( nChanid )
                            .arg( dtStartTime.toString(Qt::ISODate));

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

    CDSObject *pItem   = CDSObject::CreateVideoItem( sId,
                                                     sName,
                                                     sObjectId );
    pItem->m_bRestricted  = false;
    pItem->m_bSearchable  = true;
    pItem->m_sWriteStatus = "WRITABLE";

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

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

    pItem->SetPropValue( "genre"          , sCategory    );
    pItem->SetPropValue( "longDescription", sDescription );
    pItem->SetPropValue( "description"    , sSubtitle    );

    //pItem->SetPropValue( "producer"       , );
    //pItem->SetPropValue( "rating"         , );
    //pItem->SetPropValue( "actor"          , );
    //pItem->SetPropValue( "director"       , );
    //pItem->SetPropValue( "publisher"      , );
    //pItem->SetPropValue( "language"       , );
    //pItem->SetPropValue( "relation"       , );
    //pItem->SetPropValue( "region"         , );

    // ----------------------------------------------------------------------
    // Needed for Microsoft Media Player Compatibility
    // (Won't display correct Title without them)
    // ----------------------------------------------------------------------

    pItem->SetPropValue( "creator"       , "[Unknown Author]" );
    pItem->SetPropValue( "artist"        , "[Unknown Author]" );
    pItem->SetPropValue( "album"         , "[Unknown Series]" );
    pItem->SetPropValue( "actor"         , "[Unknown Author]" );
    pItem->SetPropValue( "date"          , dtStartTime.toString(Qt::ISODate));

    pResults->Add( pItem );

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

    StorageGroup sg(sStorageGrp, sHostName);
    QString sFilePath = sg.FindRecordingFile(sBaseName);
    QString sMimeType;

    if ( QFile::exists(sFilePath) )
        sMimeType = HTTPRequest::TestMimeType( sFilePath );
    else
        sMimeType = HTTPRequest::TestMimeType( sBaseName );


    // If we are dealing with Window Media Player 12 (i.e. Windows 7)
    // then fake the Mime type to place the recorded TV in the
    // recorded TV section.
    if (pRequest->m_eClient == CDS_ClientWMP && pRequest->m_nClientVersion >= 12.0)
    {
        sMimeType = "video/x-ms-dvr";
    }

    // DLNA string below is temp fix for ps3 seeking.
    QString sProtocol = QString( "http-get:*:%1:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000" ).arg( sMimeType  );
    QString sURI      = QString( "%1GetRecording%2").arg( sURIBase   )
                                                    .arg( sURIParams );

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

    uint uiStart = dtProgStart.toTime_t();
    uint uiEnd   = dtProgEnd.toTime_t();
    uint uiDur   = uiEnd - uiStart;

    QString sDur;

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


    pRes->AddAttribute( "duration"  , sDur      );
    pRes->AddAttribute( "size"      , QString::number( nFileSize) );

/*
    // ----------------------------------------------------------------------
    // Add Video Resource Element based on File extension (mythtv)
    // ----------------------------------------------------------------------

    sProtocol = QString( "myth:*:%1:*"     ).arg( sMimeType  );
    sURI      = QString( "myth://%1/%2" )
                   .arg( m_mapBackendIp  [ sHostName ] )
                   .arg( sBaseName );

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

    pRes->AddAttribute( "duration"  , sDur      );
    pRes->AddAttribute( "size"      , QString::number( nFileSize) );
*/

    // ----------------------------------------------------------------------
    // Add Preview URI as albumArt
    // ----------------------------------------------------------------------

    sURI = QString( "%1GetPreviewImage%2%3").arg( sURIBase   )
                                            .arg( sURIParams )
                                            .arg( "&amp;Width=160" ); 

    pItem->SetPropValue( "albumArtURI", sURI );
    Property *pProp = pItem->GetProperty("albumArtURI");
    if (pProp)
    {
        pProp->AddAttribute("dlna:profileID", "PNG_TN");
        pProp->AddAttribute("xmlns:dlna", "urn:schemas-dlna-org:metadata-1-0");
    
    }

}
示例#10
0
/** \brief Try to get a lock on the table schemalock.
 *  Prevents multiple upgrades by different programs of the same schema.
 */
bool DBUtil::TryLockSchema(MSqlQuery &query, uint timeout_secs)
{
    query.prepare("SELECT GET_LOCK('schemaLock', :TIMEOUT)");
    query.bindValue(":TIMEOUT", timeout_secs);
    return query.exec() && query.first() && query.value(0).toBool();
}
示例#11
0
/// Sets metadata from a DB row
void VideoMetadataImp::fromDBRow(MSqlQuery &query)
{
    m_title = query.value(0).toString();
    m_director = query.value(1).toString();
    m_studio = query.value(2).toString();
    m_plot = query.value(3).toString();
    m_rating = query.value(4).toString();
    m_year = query.value(5).toInt();
    m_releasedate = query.value(6).toDate();
    m_userrating = (float)query.value(7).toDouble();
    if (isnan(m_userrating) || m_userrating < 0)
        m_userrating = 0.0;
    if (m_userrating > 10.0)
        m_userrating = 10.0;
    m_length = query.value(8).toInt();
    m_filename = query.value(9).toString();
    m_hash = query.value(10).toString();
    m_showlevel = ParentalLevel(query.value(11).toInt()).GetLevel();
    m_coverfile = query.value(12).toString();
    m_inetref = query.value(13).toString();
    m_homepage = query.value(14).toString();
    m_childID = query.value(15).toUInt();
    m_browse = query.value(16).toBool();
    m_watched = query.value(17).toBool();
    m_playcommand = query.value(18).toString();
    m_categoryID = query.value(19).toInt();
    m_id = query.value(20).toInt();
    m_trailer = query.value(21).toString();
    m_screenshot = query.value(22).toString();
    m_banner = query.value(23).toString();
    m_fanart = query.value(24).toString();
    m_subtitle = query.value(25).toString();
    m_tagline = query.value(26).toString();
    m_season = query.value(27).toInt();
    m_episode = query.value(28).toInt();
    m_host = query.value(29).toString();
    m_insertdate = query.value(30).toDate();
    m_processed = query.value(31).toBool();

    VideoCategory::GetCategory().get(m_categoryID, m_category);

    // Genres
    fillGenres();

    //Countries
    fillCountries();

    // Cast
    fillCast();
}
示例#12
0
uint DBEvent::GetOverlappingPrograms(
    MSqlQuery &query, uint chanid, vector<DBEvent> &programs) const
{
    uint count = 0;
    query.prepare(
        "SELECT title,          subtitle,      description, "
        "       category,       category_type, "
        "       starttime,      endtime, "
        "       subtitletypes+0,audioprop+0,   videoprop+0, "
        "       seriesid,       programid, "
        "       partnumber,     parttotal, "
        "       syndicatedepisodenumber, "
        "       airdate,        originalairdate, "
        "       previouslyshown,listingsource, "
        "       stars+0 "
        "FROM program "
        "WHERE chanid   = :CHANID AND "
        "      manualid = 0       AND "
        "      ( ( starttime >= :STIME1 AND starttime <  :ETIME1 ) OR "
        "        ( endtime   >  :STIME2 AND endtime   <= :ETIME2 ) )");
    query.bindValue(":CHANID", chanid);
    query.bindValue(":STIME1", starttime);
    query.bindValue(":ETIME1", endtime);
    query.bindValue(":STIME2", starttime);
    query.bindValue(":ETIME2", endtime);

    if (!query.exec())
    {
        MythDB::DBError("GetOverlappingPrograms 1", query);
        return 0;
    }

    while (query.next())
    {
        MythCategoryType category_type =
            string_to_myth_category_type(query.value(4).toString());

        DBEvent prog(
            query.value(0).toString(),
            query.value(1).toString(),
            query.value(2).toString(),
            query.value(3).toString(),
            category_type,
            query.value(5).toDateTime(), query.value(6).toDateTime(),
            query.value(7).toUInt(),
            query.value(8).toUInt(),
            query.value(9).toUInt(),
            query.value(19).toDouble(),
            query.value(10).toString(),
            query.value(11).toString(),
            query.value(18).toUInt());

        prog.partnumber = query.value(12).toUInt();
        prog.parttotal  = query.value(13).toUInt();
        prog.syndicatedepisodenumber = query.value(14).toString();
        prog.airdate    = query.value(15).toUInt();
        prog.originalairdate  = query.value(16).toDate();
        prog.previouslyshown  = query.value(17).toBool();
        ;

        programs.push_back(prog);
        count++;
    }

    return count;
}
示例#13
0
bool ProgramData::IsUnchanged(
    MSqlQuery &query, uint chanid, const ProgInfo &pi)
{
    query.prepare(
        "SELECT count(*) "
        "FROM program "
        "WHERE chanid          = :CHANID     AND "
        "      starttime       = :START      AND "
        "      endtime         = :END        AND "
        "      title           = :TITLE      AND "
        "      subtitle        = :SUBTITLE   AND "
        "      description     = :DESC       AND "
        "      category        = :CATEGORY   AND "
        "      category_type   = :CATEGORY_TYPE AND "
        "      airdate         = :AIRDATE    AND "
        "      stars >= (:STARS1 - 0.001)    AND "
        "      stars <= (:STARS2 + 0.001)    AND "
        "      previouslyshown = :PREVIOUSLYSHOWN AND "
        "      title_pronounce = :TITLE_PRONOUNCE AND "
        "      audioprop       = :AUDIOPROP  AND "
        "      videoprop       = :VIDEOPROP  AND "
        "      subtitletypes   = :SUBTYPES   AND "
        "      partnumber      = :PARTNUMBER AND "
        "      parttotal       = :PARTTOTAL  AND "
        "      seriesid        = :SERIESID   AND "
        "      showtype        = :SHOWTYPE   AND "
        "      colorcode       = :COLORCODE  AND "
        "      syndicatedepisodenumber = :SYNDICATEDEPISODENUMBER AND "
        "      programid       = :PROGRAMID");

    QString cattype = myth_category_type_to_string(pi.categoryType);

    query.bindValue(":CHANID",     chanid);
    query.bindValue(":START",      pi.starttime);
    query.bindValue(":END",        pi.endtime);
    query.bindValue(":TITLE",      pi.title);
    query.bindValue(":SUBTITLE",   pi.subtitle);
    query.bindValue(":DESC",       pi.description);
    query.bindValue(":CATEGORY",   pi.category);
    query.bindValue(":CATEGORY_TYPE", cattype);
    query.bindValue(":AIRDATE",    pi.airdate);
    query.bindValue(":STARS1",     pi.stars);
    query.bindValue(":STARS2",     pi.stars);
    query.bindValue(":PREVIOUSLYSHOWN", pi.previouslyshown);
    query.bindValue(":TITLE_PRONOUNCE", pi.title_pronounce);
    query.bindValue(":AUDIOPROP",  pi.audioProps);
    query.bindValue(":VIDEOPROP",  pi.videoProps);
    query.bindValue(":SUBTYPES",   pi.subtitleType);
    query.bindValue(":PARTNUMBER", pi.partnumber);
    query.bindValue(":PARTTOTAL",  pi.parttotal);
    query.bindValue(":SERIESID",   pi.seriesId);
    query.bindValue(":SHOWTYPE",   pi.showtype);
    query.bindValue(":COLORCODE",  pi.colorcode);
    query.bindValue(":SYNDICATEDEPISODENUMBER", pi.syndicatedepisodenumber);
    query.bindValue(":PROGRAMID",  pi.programId);

    if (query.exec() && query.next())
        return query.value(0).toUInt() > 0;

    return false;
}
示例#14
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) );
}
示例#15
0
void UPnpCDSTv::AddItem( const UPnpCDSRequest    *pRequest, 
                         const QString           &sObjectId,
                         UPnpCDSExtensionResults *pResults,
                         bool                     bAddRef,
                         MSqlQuery               &query )
{
    int            nChanid      = query.value( 0).toInt();
    QDateTime      dtStartTime  = MythDate::as_utc(query.value(1).toDateTime());
    QDateTime      dtEndTime    = MythDate::as_utc(query.value(2).toDateTime());
    QString        sTitle       = query.value( 3).toString();
    QString        sSubtitle    = query.value( 4).toString();
    QString        sDescription = query.value( 5).toString();
    QString        sCategory    = query.value( 6).toString();
    QString        sHostName    = query.value( 7).toString();
    QString        sRecGroup    = query.value( 8).toString();
    uint64_t       nFileSize    = query.value( 9).toULongLong();
    QString        sBaseName    = query.value(10).toString();

    QDateTime      dtProgStart  =
        MythDate::as_utc(query.value(11).toDateTime());
    QDateTime      dtProgEnd    =
        MythDate::as_utc(query.value(12).toDateTime());
    QString        sStorageGrp  = query.value(13).toString();

    QString        sInetRef     = query.value(14).toString();

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

    if (!m_mapBackendIp.contains( sHostName ))
        m_mapBackendIp[ sHostName ] = gCoreContext->GetBackendServerIP4(sHostName);

    if (!m_mapBackendPort.contains( sHostName ))
        m_mapBackendPort[ sHostName ] = gCoreContext->GetBackendStatusPort(sHostName);

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

    QString sName      = sTitle + ": " + (sSubtitle.isEmpty() ? sDescription.left(128) : sSubtitle);

    QString sURIBase   = QString( "http://%1:%2/Content/" )
                            .arg( m_mapBackendIp  [ sHostName ] )
                            .arg( m_mapBackendPort[ sHostName ] );

    QString sURIParams = QString( "?ChanId=%1&amp;StartTime=%2" )
                            .arg( nChanid )
                            .arg( dtStartTime.toString(Qt::ISODate));

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

    CDSObject *pItem   = CDSObject::CreateVideoItem( sId,
                                                     sName,
                                                     sObjectId );
    pItem->m_bRestricted  = false;
    pItem->m_bSearchable  = true;
    pItem->m_sWriteStatus = "WRITABLE";

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

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

    pItem->SetPropValue( "genre"          , sCategory    );
    pItem->SetPropValue( "longDescription", sDescription );
    pItem->SetPropValue( "description"    , sSubtitle    );

    //pItem->SetPropValue( "producer"       , );
    //pItem->SetPropValue( "rating"         , );
    //pItem->SetPropValue( "actor"          , );
    //pItem->SetPropValue( "director"       , );
    //pItem->SetPropValue( "publisher"      , );
    //pItem->SetPropValue( "language"       , );
    //pItem->SetPropValue( "relation"       , );
    //pItem->SetPropValue( "region"         , );

    // ----------------------------------------------------------------------
    // Needed for Microsoft Media Player Compatibility
    // (Won't display correct Title without them)
    // ----------------------------------------------------------------------

    pItem->SetPropValue( "creator"       , "[Unknown Author]" );
    pItem->SetPropValue( "artist"        , "[Unknown Author]" );
    pItem->SetPropValue( "album"         , "[Unknown Series]" );
    pItem->SetPropValue( "actor"         , "[Unknown Author]" );
    pItem->SetPropValue( "date"          , dtStartTime.toString(Qt::ISODate));

    pResults->Add( pItem );

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

    StorageGroup sg(sStorageGrp, sHostName);
    QString sFilePath = sg.FindFile(sBaseName);
    QString sMimeType;

    if ( QFile::exists(sFilePath) )
        sMimeType = HTTPRequest::TestMimeType( sFilePath );
    else
        sMimeType = HTTPRequest::TestMimeType( sBaseName );


    // If we are dealing with Window Media Player 12 (i.e. Windows 7)
    // then fake the Mime type to place the recorded TV in the
    // recorded TV section.
    if (pRequest->m_eClient == CDS_ClientWMP &&
        pRequest->m_nClientVersion >= 12.0)
    {
        sMimeType = "video/x-ms-dvr";
    }

    // If we are dealing with a Sony Blu-ray player then we fake the
    // MIME type to force the video to appear
    if ( pRequest->m_eClient == CDS_ClientSonyDB )
    {
        sMimeType = "video/avi";
    }


    // DLNA string below is temp fix for ps3 seeking.
    QString sProtocol = QString( "http-get:*:%1:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000" ).arg( sMimeType  );
    QString sURI      = QString( "%1GetRecording%2").arg( sURIBase   )
                                                    .arg( sURIParams );

    // Sony BDPS370 requires a DLNA Profile Name
    // FIXME: detection to determine the correct DLNA Profile Name
    if (sMimeType == "video/mpeg")
    {
        sProtocol += ";DLNA.ORG_PN=MPEG_TS_SD_NA_ISO";
    }

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

    uint uiStart = dtProgStart.toTime_t();
    uint uiEnd   = dtProgEnd.toTime_t();
    uint uiDur   = uiEnd - uiStart;
    
    MSqlQuery query2(MSqlQuery::InitCon());
    query2.prepare( "SELECT data FROM recordedmarkup WHERE chanid=:CHANID AND "
                    "starttime=:STARTTIME AND type = 33" );
    query2.bindValue(":CHANID", (int)nChanid);
    query2.bindValue(":STARTTIME", dtStartTime);
    if (query2.exec() && query2.next())
        uiDur = query2.value(0).toUInt() / 1000;

    QString sDur;

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

    LOG(VB_UPNP, LOG_DEBUG, "Duration: " + sDur );

    pRes->AddAttribute( "duration"  , sDur      );
    pRes->AddAttribute( "size"      , QString::number( nFileSize) );

/*
    // ----------------------------------------------------------------------
    // Add Video Resource Element based on File extension (mythtv)
    // ----------------------------------------------------------------------

    sProtocol = QString( "myth:*:%1:*"     ).arg( sMimeType  );
    sURI      = QString( "myth://%1/%2" )
                   .arg( m_mapBackendIp  [ sHostName ] )
                   .arg( sBaseName );

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

    pRes->AddAttribute( "duration"  , sDur      );
    pRes->AddAttribute( "size"      , QString::number( nFileSize) );
*/

    // ----------------------------------------------------------------------
    // Add Preview URI as <res>
    // MUST be _TN and 160px
    // ----------------------------------------------------------------------

    sURI = QString( "%1GetPreviewImage%2%3").arg( sURIBase   )
                                            .arg( sURIParams )
                                            .arg( "&amp;Width=160" );

    // TODO: Must be JPG for minimal compliance
    sProtocol = QString( "http-get:*:image/png:DLNA.ORG_PN=PNG_TN");
    pItem->AddResource( sProtocol, sURI );

    // ----------------------------------------------------------------------
    // Add Artwork URI as albumArt
    // ----------------------------------------------------------------------

    sURI = QString( "%1GetRecordingArtwork?Type=coverart&amp;Inetref=%3")
                                              .arg( sURIBase   )
                                              .arg( sInetRef   );

    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 = sURI;
            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 = sURI;
            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");
        }

        // Medium
        pProp = propList.at(2);
        if (pProp)
        {
            // Must be no more than 1024x768
            pProp->m_sValue = sURI;
            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");
        }

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


}
示例#16
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      );
}