Ticket #3842: 3842-head-v4.patch

File 3842-head-v4.patch, 34.0 KB (added by danielk, 17 years ago)

Untested update for head patch which adds program id updates

  • libs/libmythtv/videosource.h

     
    2121class DiSEqCDevTree;
    2222class DiSEqCDevSettings;
    2323
     24static inline bool is_grabber_external(const QString &grabber)
     25{
     26    return !(grabber == "datadirect" ||
     27             grabber == "eitonly" ||
     28             grabber == "schedulesdirect1" ||
     29             grabber == "/bin/true");
     30}
     31
     32static inline bool is_grabber_datadirect(const QString &grabber)
     33{
     34    return (grabber == "datadirect") || (grabber == "schedulesdirect1");
     35}
     36
     37static inline bool is_grabber_labs(const QString &grabber)
     38{
     39    return grabber == "datadirect";
     40}
     41
    2442class VideoSourceDBStorage : public SimpleDBStorage
    2543{
    2644  protected:
     
    110128{
    111129    Q_OBJECT
    112130  public:
    113     DataDirect_config(const VideoSource& _parent, int _source = DD_ZAP2IT);
     131    DataDirect_config(const VideoSource& _parent, int _ddsource);
    114132
    115133    virtual void load(void);
    116134
  • libs/libmythtv/dbcheck.cpp

     
    88
    99#include "mythcontext.h"
    1010#include "mythdbcon.h"
     11#include "datadirect.h" // for DataDirectProcessor::FixProgramIDs
    1112
    1213/// This is the DB schema version expected by the running MythTV instance.
    1314const QString currentDatabaseVersion = "1195";
     
    467468
    468469    bool ret = doUpgradeTVDatabaseSchema();
    469470
     471    if (!gContext->GetNumSetting("MythFillFixProgramIDsHasRunOnce", 0))
     472        DataDirectProcessor::FixProgramIDs();
     473
    470474    if (ret)
    471475        VERBOSE(VB_IMPORTANT, "Database Schema upgrade complete, unlocking.");
    472476    else
  • libs/libmythtv/datadirect.h

     
    1313
    1414enum DD_PROVIDERS
    1515{
    16     DD_ZAP2IT = 0,
    17     DD_PROVIDER_COUNT,
     16    DD_ZAP2IT           = 0,
     17    DD_SCHEDULES_DIRECT = 1,
     18    DD_PROVIDER_COUNT   = 2,
    1819};
    1920
    2021class DataDirectURLs
     
    254255                        QString userid = "", QString password = "");
    255256   ~DataDirectProcessor();
    256257
     258    QString CreateTempDirectory(void);
     259
    257260    // web service commands
    258261    bool GrabData(const QDateTime pstartdate, const QDateTime penddate);
    259262    bool GrabNextSuggestedTime(void);
     
    303306    RawLineup GetRawLineup( const QString &lineupid) const;
    304307
    305308    // sets
    306     void SetUserID(QString uid)                 { userid             = uid;  }
    307     void SetPassword(QString pwd)               { password           = pwd;  }
     309    void SetUserID(const QString &uid);
     310    void SetPassword(const QString &pwd);
    308311    void SetListingsProvider(uint i)
    309312        { listings_provider = i % DD_PROVIDER_COUNT; }
    310     void SetInputFile(const QString &file)      { inputfilename      = file; }
    311313
     314    void SetInputFile(const QString &file);
     315    void SetCacheData(bool cd) { cachedata = cd; }
     316
    312317    // static commands (these update temp DB tables)
    313318    static void UpdateStationViewTable(QString lineupid);
    314319    static void UpdateProgramViewTable(uint sourceid);
     
    318323    static bool UpdateChannelsUnsafe(uint sourceid);
    319324    static void DataDirectProgramUpdate(void);
    320325
     326    // static command, makes Labs and Schedules Direct ProgramIDs compatible.
     327    static void FixProgramIDs(void);
     328
    321329  private:
    322330    void CreateTempTables(void);
    323331    void CreateATempTable(const QString &ptablename,
     
    326334    bool ParseLineups(const QString &documentFile);
    327335    bool ParseLineup(const QString &lineupid, const QString &documentFile);
    328336
     337    QString GetPostFilename(void) const;
     338    QString GetResultFilename(void) const;
     339    QString GetCookieFilename(void) const;
     340
    329341    void SetAll(const QString &lineupid, bool val);
    330342    void SetDDProgramsStartAt(QDateTime begts)  { actuallistingsfrom = begts; }
    331343    void SetDDProgramsEndAt(QDateTime endts)    { actuallistingsto   = endts; }
     
    346358
    347359    QString       userid;
    348360    QString       password;
     361    QString       tmpDir;
     362    bool          cachedata;
    349363
    350364    QDateTime     actuallistingsfrom;
    351365    QDateTime     actuallistingsto;
     
    356370    DDLineupList  lineups;
    357371    DDLineupMap   lineupmaps;
    358372
    359     RawLineupMap  rawlineups;
    360     QString      tmpPostFile;
    361     QString      tmpResultFile;
    362     QString      cookieFile;
    363     QDateTime     cookieFileDT;
     373    RawLineupMap    rawlineups;
     374    mutable QString tmpPostFile;
     375    mutable QString tmpResultFile;
     376    mutable QString cookieFile;
     377    QDateTime       cookieFileDT;
    364378};
    365379
    366380#endif
  • libs/libmythtv/datadirect.cpp

     
    66
    77// Qt headers
    88#include <qmap.h>
     9#include <qdir.h>
    910#include <qfile.h>
    1011#include <qstring.h>
    1112#include <qregexp.h>
     
    2526#define SHOW_WGET_OUTPUT 0
    2627
    2728#define LOC QString("DataDirect: ")
     29#define LOC_WARN QString("DataDirect, Warning: ")
    2830#define LOC_ERR QString("DataDirect, Error: ")
    2931
    3032static QMutex lineup_type_lock;
     
    511513    return true;
    512514}
    513515
    514 static QString makeTempFile(QString name_template)
    515 {
    516     const char *tmp = name_template.ascii();
    517     char *ctemplate = strdup(tmp);
    518     int ret = mkstemp(ctemplate);
    519     QString tmpFileName(ctemplate);
    520     free(ctemplate);
    521 
    522     if (ret == -1)
    523     {
    524         VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating temp file from " +
    525                 QString("template '%1'").arg(name_template) + ENO);
    526         return name_template;
    527     }
    528     close(ret);
    529 
    530     return tmpFileName;
    531 }
    532 
    533516DataDirectProcessor::DataDirectProcessor(uint lp, QString user, QString pass) :
    534517    listings_provider(lp % DD_PROVIDER_COUNT),
    535     userid(user),               password(pass),
    536     inputfilename(""),          tmpPostFile(""),
    537     tmpResultFile(""),          cookieFile(""),
     518    userid(user),                   password(pass),
     519    tmpDir("/tmp"),                 cachedata(false),
     520    inputfilename(""),              tmpPostFile(QString::null),
     521    tmpResultFile(QString::null),   cookieFile(QString::null),
    538522    cookieFileDT()
    539523{
    540524    DataDirectURLs urls0(
     
    542526        "http://datadirect.webservices.zap2it.com/tvlistings/xtvdService",
    543527        "http://labs.zap2it.com",
    544528        "/ztvws/ztvws_login/1,1059,TMS01-1,00.html");
     529    DataDirectURLs urls1(
     530        "Schedules Direct",
     531        "http://webservices.schedulesdirect.tmsdatadirect.com"
     532        "/schedulesdirect/tvlistings/xtvdService",
     533        "http://schedulesdirect.org",
     534        "/login/index.php");
    545535    providers.push_back(urls0);
    546 
    547     QString tmpDir = "/tmp";
    548     tmpPostFile   = makeTempFile(tmpDir + "/mythtv_post_XXXXXX");
    549     tmpResultFile = makeTempFile(tmpDir + "/mythtv_result_XXXXXX");
    550     cookieFile    = makeTempFile(tmpDir + "/mythtv_cookies_XXXXXX");
     536    providers.push_back(urls1);
    551537}
    552538
    553539DataDirectProcessor::~DataDirectProcessor()
    554540{
    555     unlink(tmpPostFile.ascii());
    556     unlink(tmpResultFile.ascii());
    557     unlink(cookieFile.ascii());
     541    VERBOSE(VB_GENERAL, LOC + "Deleting temporary files");
     542
     543    if (!tmpPostFile.isEmpty())
     544        unlink(tmpPostFile.ascii());
     545
     546    if (!tmpResultFile.isEmpty())
     547        unlink(tmpResultFile.ascii());
     548
     549    if (!cookieFile.isEmpty())
     550        unlink(cookieFile.ascii());
     551
     552    QDir d(tmpDir, "mythtv_dd_cache_*", QDir::Name,
     553           QDir::Files | QDir::NoSymLinks);
     554
     555    for (uint i = 0; i < d.count(); i++)
     556    {
     557        //cout<<"deleting '"<<tmpDir<<"/"<<d[i]<<"'"<<endl;
     558        unlink((tmpDir + "/" + d[i]).ascii());
     559    }
     560
     561    if (tmpDir != "/tmp")
     562        rmdir(tmpDir.ascii());
    558563}
    559564
     565QString DataDirectProcessor::CreateTempDirectory(void)
     566{
     567    if (tmpDir == "/tmp")
     568        tmpDir = createTempFile("/tmp/mythtv_ddp_XXXXXX", true);
     569    return QDeepCopy<QString>(tmpDir);
     570}
     571
    560572void DataDirectProcessor::UpdateStationViewTable(QString lineupid)
    561573{
    562574    MSqlQuery query(MSqlQuery::DDCon());
     
    805817    //cerr << "Done...\n";
    806818}
    807819
     820void DataDirectProcessor::FixProgramIDs(void)
     821{
     822    VERBOSE(VB_GENERAL, "DataDirectProcessor::FixProgramIDs() -- begin");
     823
     824    MSqlQuery query(MSqlQuery::DDCon());
     825    query.prepare(
     826        "UPDATE recorded "
     827        "SET programid=CONCAT(SUBSTRING(programid, 1, 2), "
     828        "                     '00', SUBSTRING(programid, 3)) "
     829        "WHERE length(programid) = 12");
     830
     831    if (!query.exec())
     832    {
     833        MythContext::DBError("Fixing program ids in recorded", query);
     834        return;
     835    }
     836
     837    query.prepare(
     838        "UPDATE oldrecorded "
     839        "SET programid=CONCAT(SUBSTRING(programid, 1, 2), "
     840        "                     '00', SUBSTRING(programid, 3)) "
     841        "WHERE length(programid) = 12");
     842
     843    if (!query.exec())
     844    {
     845        MythContext::DBError("Fixing program ids in oldrecorded", query);
     846        return;
     847    }
     848
     849    gContext->SetSetting("MythFillFixProgramIDsHasRunOnce", "1");
     850
     851    VERBOSE(VB_GENERAL, "DataDirectProcessor::FixProgramIDs() -- end");
     852}
     853
    808854FILE *DataDirectProcessor::DDPost(
    809855    QString    ddurl,
    810856    QString    postFilename, QString    inputFile,
     
    870916    VERBOSE(VB_GENERAL, "Grabbing next suggested grabbing time");
    871917
    872918    QString ddurl = providers[listings_provider].webServiceURL;
    873          
    874     QFile postfile(tmpPostFile);
     919
     920    QFile postfile(GetPostFilename());
    875921    if (!postfile.open(IO_WriteOnly))
    876922    {
    877923        VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Opening '%1'")
    878                 .arg(tmpPostFile) + ENO);
     924                .arg(GetPostFilename()) + ENO);
    879925        return false;
    880926    }
    881927
     
    896942
    897943    QString command = QString("wget --http-user='%1' --http-passwd='%2' "
    898944                              "--post-file='%3' %4 --output-document='%5'")
    899         .arg(GetUserID()).arg(GetPassword()).arg(tmpPostFile)
    900         .arg(ddurl).arg(tmpResultFile);
     945        .arg(GetUserID()).arg(GetPassword()).arg(GetPostFilename())
     946        .arg(ddurl).arg(GetResultFilename());
    901947
    902948    if (SHOW_WGET_OUTPUT)
    903949        VERBOSE(VB_GENERAL, "command: "<<command<<endl);
     
    909955    QDateTime NextSuggestedTime;
    910956    QDateTime BlockedTime;
    911957
    912     QFile file(tmpResultFile);
     958    QFile file(GetResultFilename());
    913959
    914960    bool GotNextSuggestedTime = false;
    915961    bool GotBlockedTime = false;
     
    9941040
    9951041    QString err = "";
    9961042    QString ddurl = providers[listings_provider].webServiceURL;
     1043    QString inputfile = inputfilename;
     1044    QString cache_dd_data = QString::null;
    9971045
    998     FILE *fp = DDPost(ddurl, tmpPostFile, inputfilename,
     1046    if (cachedata)
     1047    {
     1048        cache_dd_data = tmpDir + QString("/mythtv_dd_cache_%1_%2_%3_%4")
     1049            .arg(GetListingsProvider())
     1050            .arg(GetUserID().ascii())
     1051            .arg(pstartDate.toString())
     1052            .arg(pendDate.toString());
     1053
     1054        if (QFile(cache_dd_data).exists() && inputfilename.isEmpty())
     1055        {
     1056            VERBOSE(VB_GENERAL, LOC + "Copying from DD cache");
     1057            inputfile = cache_dd_data;
     1058        }
     1059    }
     1060
     1061    FILE *fp = DDPost(ddurl, GetPostFilename(), inputfile,
    9991062                      GetUserID(), GetPassword(),
    10001063                      pstartDate, pendDate, err);
    10011064    if (!fp)
     
    10051068        return false;
    10061069    }
    10071070
     1071    if (cachedata && (inputfile != cache_dd_data))
     1072    {
     1073        QFile in, out(cache_dd_data);
     1074        bool ok = out.open(IO_WriteOnly);
     1075        if (!ok)
     1076        {
     1077            VERBOSE(VB_IMPORTANT, LOC_WARN +
     1078                    "Can not open DD cache file in '" +
     1079                    tmpDir + "' for writing!");
     1080        }
     1081        else
     1082        {
     1083            VERBOSE(VB_GENERAL, LOC + "Saving listings to DD cache");
     1084            ok = in.open(IO_ReadOnly, fp);
     1085            out.close(); // let copy routine handle dst file
     1086        }
     1087
     1088        if (ok)
     1089        {
     1090            if (copy(out, in))
     1091            {
     1092                pclose(fp);
     1093                fp = fopen(cache_dd_data.ascii(), "r");
     1094            }
     1095            else
     1096            {
     1097                VERBOSE(VB_IMPORTANT,
     1098                        LOC_ERR + "Failed to save DD cache! "
     1099                        "redownloading data...");
     1100                cachedata = false;
     1101                pclose(fp);
     1102                fp = DDPost(ddurl, GetPostFilename(), inputfile,
     1103                            GetUserID(), GetPassword(),
     1104                            pstartDate, pendDate, err);
     1105            }
     1106        }
     1107    }
     1108
    10081109    QFile f;
    10091110    if (f.open(IO_ReadOnly, fp))
    10101111    {
     
    10831184        "  channelMinor char(3) )";
    10841185
    10851186    dd_tables["dd_schedule"] =
    1086         "( programid char(12),           stationid char(12), "
     1187        "( programid char(40),           stationid char(12), "
    10871188        "  scheduletime datetime,        duration time,      "
    10881189        "  isrepeat bool,                stereo bool,        "
    10891190        "  subtitled bool,               hdtv bool,          "
     
    10931194        "INDEX progidx (programid) )";
    10941195
    10951196    dd_tables["dd_program"] =
    1096         "( programid char(12) NOT NULL,  seriesid char(12),     "
     1197        "( programid char(40) NOT NULL,  seriesid char(12),     "
    10971198        "  title varchar(120),           subtitle varchar(150), "
    10981199        "  description text,             mpaarating char(5),    "
    10991200        "  starrating char(5),           runtime time,          "
     
    11151216        "  partnumber int,               parttotal int,               "
    11161217        "  seriesid char(12),            originalairdate date,        "
    11171218        "  showtype varchar(30),         colorcode varchar(20),       "
    1118         "  syndicatedepisodenumber varchar(20), programid char(12),   "
     1219        "  syndicatedepisodenumber varchar(20), programid char(40),   "
    11191220        "  tvrating char(5),             mpaarating char(5),          "
    11201221        "INDEX progidx (programid))";
    11211222
    11221223    dd_tables["dd_productioncrew"] =
    1123         "( programid char(12),           role char(30),    "
     1224        "( programid char(40),           role char(30),    "
    11241225        "  givenname char(20),           surname char(20), "
    11251226        "  fullname char(41), "
    11261227        "INDEX progidx (programid), "
    11271228        "INDEX nameidx (fullname))";
    11281229
    11291230    dd_tables["dd_genre"] =
    1130         "( programid char(12) NOT NULL,  class char(30), "
     1231        "( programid char(40) NOT NULL,  class char(30), "
    11311232        "  relevance char(1), "
    11321233        "INDEX progidx (programid))";
    11331234
     
    11481249    QString labsURL   = providers[listings_provider].webURL;
    11491250    QString loginPage = providers[listings_provider].loginPage;
    11501251
    1151     bool ok = Post(labsURL + loginPage, list, tmpResultFile, "", cookieFile);
     1252    bool ok = Post(labsURL + loginPage, list, GetResultFilename(), "",
     1253                   GetCookieFilename());
    11521254
    1153     bool got_cookie = QFileInfo(cookieFile).size() > 100;
     1255    bool got_cookie = QFileInfo(GetCookieFilename()).size() > 100;
    11541256
    1155     ok &= got_cookie && (!parse_lineups || ParseLineups(tmpResultFile));
     1257    ok &= got_cookie && (!parse_lineups || ParseLineups(GetResultFilename()));
    11561258    if (ok)
    11571259        cookieFileDT = QDateTime::currentDateTime();
    11581260
     
    11751277    list.push_back(PostItem("submit",    "Modify"));
    11761278
    11771279    QString labsURL = providers[listings_provider].webURL;
    1178     bool ok = Post(labsURL + (*it).get_action, list, tmpResultFile,
    1179                    cookieFile, "");
     1280    bool ok = Post(labsURL + (*it).get_action, list, GetResultFilename(),
     1281                   GetCookieFilename(), "");
    11801282
    1181     return ok && ParseLineup(lineupid, tmpResultFile);
     1283    return ok && ParseLineup(lineupid, GetResultFilename());
    11821284}
    11831285
    11841286void DataDirectProcessor::SetAll(const QString &lineupid, bool val)
     
    14571559            .arg(lineupid).arg(list.size() - 1));
    14581560
    14591561    QString labsURL = providers[listings_provider].webURL;
    1460     return Post(labsURL + lineup.set_action, list, "", cookieFile, "");
     1562    return Post(labsURL + lineup.set_action, list, "",
     1563                GetCookieFilename(), "");
    14611564}
    14621565
    14631566bool DataDirectProcessor::UpdateListings(uint sourceid)
     
    15341637    return (*it);
    15351638}
    15361639
     1640QString DataDirectProcessor::GetPostFilename(void) const
     1641{
     1642    if (tmpPostFile.isEmpty())
     1643        tmpPostFile = createTempFile(tmpDir + "/mythtv_post_XXXXXX");
     1644    return QDeepCopy<QString>(tmpPostFile);
     1645}
     1646
     1647QString DataDirectProcessor::GetResultFilename(void) const
     1648{
     1649    if (tmpResultFile.isEmpty())
     1650        tmpResultFile = createTempFile(tmpDir + "/mythtv_result_XXXXXX");
     1651    return QDeepCopy<QString>(tmpResultFile);
     1652}
     1653
     1654QString DataDirectProcessor::GetCookieFilename(void) const
     1655{
     1656    if (cookieFile.isEmpty())
     1657        cookieFile = createTempFile(tmpDir + "/mythtv_cookies_XXXXXX");
     1658    return QDeepCopy<QString>(cookieFile);
     1659}
     1660
     1661void DataDirectProcessor::SetUserID(const QString &uid)
     1662{
     1663    userid = QDeepCopy<QString>(uid);
     1664}
     1665
     1666void DataDirectProcessor::SetPassword(const QString &pwd)
     1667{
     1668    password = QDeepCopy<QString>(pwd);
     1669}
     1670
     1671void DataDirectProcessor::SetInputFile(const QString &file)
     1672{
     1673    inputfilename = QDeepCopy<QString>(file);
     1674}
     1675
    15371676bool DataDirectProcessor::Post(QString url, const PostList &list,
    15381677                               QString documentFile,
    15391678                               QString inCookieFile, QString outCookieFile)
  • libs/libmythtv/videosource.cpp

     
    2020#include <qmap.h>
    2121#include <qdir.h>
    2222#include <qprocess.h>
     23#include <qdatetime.h>
    2324
    2425// MythTV headers
    2526#include "mythconfig.h"
     
    295296{
    296297  public:
    297298    DataDirectPassword(const VideoSource &parent) :
    298         LineEditSetting(this), VideoSourceDBStorage(this, parent, "password")
     299        LineEditSetting(this, true),
     300        VideoSourceDBStorage(this, parent, "password")
    299301    {
     302        SetPasswordEcho(true);
    300303        setLabel(QObject::tr("Password"));
    301304    }
    302305};
     
    307310{
    308311    (void) uid;
    309312    (void) pwd;
    310     (void) _source;
    311313#ifdef USING_BACKEND
    312314    if (uid.isEmpty() || pwd.isEmpty())
    313315        return;
     
    348350void DataDirect_config::load()
    349351{
    350352    VerticalConfigurationGroup::load();
    351     if ((userid->getValue() != lastloadeduserid) ||
    352         (password->getValue() != lastloadedpassword))
     353    bool is_sd_userid = userid->getValue().contains("@") > 0;
     354    bool match = ((is_sd_userid  && (source == DD_SCHEDULES_DIRECT)) ||
     355                  (!is_sd_userid && (source == DD_ZAP2IT)));
     356    if (((userid->getValue() != lastloadeduserid) ||
     357         (password->getValue() != lastloadedpassword)) && match)
    353358    {
    354359        lineupselector->fillSelections(userid->getValue(),
    355360                                       password->getValue(),
     
    442447        "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
    443448        "channel numbers, so you have to set them manually.");
    444449
    445     if (grabber != "datadirect" && grabber != "eitonly" &&
    446         grabber != "/bin/true")
     450    if (is_grabber_external(grabber))
    447451    {
    448452        VERBOSE(VB_IMPORTANT, "\n" << err_msg);
    449453        MythPopupBox::showOkPopup(
     
    508512    // only save settings for the selected grabber
    509513    setSaveAll(false);
    510514
    511     addTarget("datadirect", new DataDirect_config(parent));
    512     grabber->addSelection("North America (DataDirect) (Internal)", "datadirect");
     515    addTarget("schedulesdirect1",
     516              new DataDirect_config(parent, DD_SCHEDULES_DIRECT));
     517    grabber->addSelection("North America (SchedulesDirect.org) "
     518                          "(Internal)", "schedulesdirect1");
    513519
     520#if 1
     521    addTarget("datadirect", new DataDirect_config(parent, DD_ZAP2IT));
     522    grabber->addSelection(
     523        "North America (TMS Labs) (Internal)", "datadirect");
     524#endif
     525
    514526    addTarget("eitonly", new EITOnly_config(parent));
    515527    grabber->addSelection("Transmitted guide only (EIT)", "eitonly");
    516528
  • libs/libmyth/settings.cpp

     
    639639        connect(edit, SIGNAL(changeHelpText(QString)), cg,
    640640                SIGNAL(changeHelpText(QString)));
    641641
    642     edit->setRW(rw);
     642    setRW(rw);
     643    SetPasswordEcho(password_echo);
    643644
    644645    return widget;
    645646}
     
    664665    }
    665666}
    666667
     668void LineEditSetting::SetPasswordEcho(bool b)
     669{
     670    password_echo = b;
     671    if (edit)
     672        edit->setEchoMode(b ? QLineEdit::Password : QLineEdit::Normal);
     673}
     674
    667675QWidget* SliderSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
    668676                                     const char* widgetName) {
    669677    QHBox* widget;
  • libs/libmyth/util.cpp

     
    3232#include <qpainter.h>
    3333#include <qpixmap.h>
    3434#include <qfont.h>
     35#include <qfile.h>
    3536
    3637// Myth headers
    3738#include "mythconfig.h"
     
    603604
    604605    return false;
    605606}
     607
     608/** \fn  Copy(QFile&,QFile&,uint)
     609 *  \brief Copies src file to dst file.
     610 *
     611 *   If the dst file is open, it must be open for writing.
     612 *   If the src file is open, if must be open for reading.
     613 *
     614 *   The files will be in the same open or close state after
     615 *   this function runs as they were prior to this function being called.
     616 *
     617 *   This function does not care if the files are actual files.
     618 *   For compatibility with pipes and socket streams the file location
     619 *   will not be reset to 0 at the end of this function. If the function
     620 *   is succesful the file pointers will be at the end of the copied
     621 *   data.
     622 *
     623 *  \param dst Destination QFile
     624 *  \param src Source QFile
     625 *  \param block_size Optional block size in bytes, must be at least 1024,
     626 *                    otherwise the default of 16 KB will be used.
     627 *  \return bytes copied on success, -1 on failure.
     628 */
     629long long copy(QFile &dst, QFile &src, uint block_size)
     630{
     631    uint buflen = (block_size < 1024) ? (16 * 1024) : block_size;
     632    char *buf = new char[buflen];
     633    bool odst = false, osrc = false;
     634
     635    if (!buf)
     636        return -1LL;
     637
     638    if (!dst.isWritable() && !dst.isOpen())
     639        odst = dst.open(IO_Raw|IO_WriteOnly|IO_Truncate);
     640
     641    if (!src.isReadable() && !src.isOpen())
     642        osrc = src.open(IO_Raw|IO_ReadOnly);
     643
     644    bool ok = dst.isWritable() && src.isReadable();
     645    long long total_bytes = 0LL;
     646    while (ok)
     647    {
     648        long long rlen, wlen, off = 0;
     649        rlen = src.readBlock(buf, buflen);
     650        if (rlen<0)
     651        {
     652            ok = false;
     653            break;
     654        }
     655        if (rlen==0)
     656            break;
     657
     658        total_bytes += (long long) rlen;
     659
     660        while ((rlen-off>0) && ok)
     661        {
     662            wlen = dst.writeBlock(buf + off, rlen - off);
     663            if (wlen>=0)
     664                off+= wlen;
     665            if (wlen<0)
     666                ok = false;
     667        }
     668    }
     669    delete[] buf;
     670
     671    if (odst)
     672        dst.close();
     673
     674    if (osrc)
     675        src.close();
     676
     677    return (ok) ? total_bytes : -1LL;
     678}
     679
     680QString createTempFile(QString name_template, bool dir)
     681{
     682    const char *tmp = name_template.ascii();
     683    char *ctemplate = strdup(tmp);
     684    int ret = -1;
     685
     686    if (dir)
     687    {
     688        ret = (mkdtemp(ctemplate)) ? 0 : -1;
     689    }
     690    else
     691    {
     692        ret = mkstemp(ctemplate);
     693    }
     694
     695    QString tmpFileName(ctemplate);
     696    free(ctemplate);
     697
     698    if (ret == -1)
     699    {
     700        VERBOSE(VB_IMPORTANT, QString("createTempFile(%1), Error ")
     701                .arg(name_template) + ENO);
     702        return name_template;
     703    }
     704
     705    if (!dir && (ret >= 0))
     706        close(ret);
     707
     708    return tmpFileName;
     709}
     710
  • libs/libmyth/util.h

     
    1616class QImage;
    1717class QPainter;
    1818class QFont;
     19class QFile;
    1920
    2021class MPUBLIC MythTimer
    2122{
     
    7374MPUBLIC bool ping(const QString &host, int timeout);
    7475MPUBLIC bool telnet(const QString &host, int port);
    7576
     77MPUBLIC long long copy(QFile &dst, QFile &src, uint block_size = 0);
     78MPUBLIC QString createTempFile(QString name_template = "/tmp/mythtv_XXXXX",
     79                               bool dir = false);
     80
    7681#endif // UTIL_H_
  • libs/libmyth/mythcontext.h

     
    208208
    209209/// Update this whenever the plug-in API changes.
    210210/// Including changes in the libmythtv class methods used by plug-ins.
    211 #define MYTH_BINARY_VERSION "0.20.20070717-1"
     211#define MYTH_BINARY_VERSION "0.20.20070817-1"
    212212
    213213/** \brief Increment this whenever the MythTV network protocol changes.
    214214 *
  • libs/libmyth/settings.h

     
    200200{
    201201  protected:
    202202    LineEditSetting(Storage *_storage, bool readwrite = true) :
    203         Setting(_storage), edit(NULL), rw(readwrite) { }
     203        Setting(_storage), edit(NULL), rw(readwrite), password_echo(false) { }
    204204
    205205  public:
    206206    virtual QWidget* configWidget(ConfigurationGroup *cg, QWidget* parent,
     
    217217
    218218    virtual void setEnabled(bool b);
    219219    virtual void setVisible(bool b);
     220    virtual void SetPasswordEcho(bool b);
    220221
    221222private:
    222223    MythLineEdit* edit;
    223224    bool rw;
     225    bool password_echo;
    224226};
    225227
    226228// TODO: set things up so that setting the value as a string emits
  • programs/mythfilldatabase/filldata.cpp

     
    2323#include "mythcontext.h"
    2424#include "mythdbcon.h"
    2525
     26// libmythtv headers
     27#include "videosource.h" // for is_grabber..
     28
    2629// filldata headers
    2730#include "filldata.h"
    2831
     
    4447        icon_data.UpdateSourceIcons(source.id);
    4548
    4649    // Unselect channels not in users lineup for DVB, HDTV
    47     if (!insert_channels && (new_channels > 0))
     50    if (!insert_channels && (new_channels > 0) &&
     51        is_grabber_labs(source.xmltvgrabber))
    4852    {
    4953        bool ok0 = (logged_in == source.userid);
    5054        bool ok1 = (raw_lineup == source.id);
     
    6973
    7074bool FillData::DataDirectUpdateChannels(Source source)
    7175{
     76    if (!is_grabber_labs(source.xmltvgrabber))
     77    {
     78        VERBOSE(VB_IMPORTANT, "FillData: We only support "
     79                "DataDirectUpdateChannels with TMS Labs channel editor");
     80        return false;
     81    }
     82
    7283    ddprocessor.SetListingsProvider(DD_ZAP2IT);
    7384    ddprocessor.SetUserID(source.userid);
    7485    ddprocessor.SetPassword(source.password);
     
    8798bool FillData::grabDDData(Source source, int poffset,
    8899                          QDate pdate, int ddSource)
    89100{
     101    if (source.dd_dups.empty())
     102        ddprocessor.SetCacheData(false);
     103    else
     104    {
     105        VERBOSE(VB_GENERAL, QString(
     106                    "This DataDirect listings source is "
     107                    "shared by %1 MythTV lineups")
     108                .arg(source.dd_dups.size()+1));
     109        if (source.id > source.dd_dups[0])
     110        {
     111            VERBOSE(VB_IMPORTANT, "We should use cached data for this one");
     112        }
     113        else if (source.id < source.dd_dups[0])
     114        {
     115            VERBOSE(VB_IMPORTANT, "We should keep data around after this one");
     116        }
     117        ddprocessor.SetCacheData(true);
     118    }
     119
    90120    ddprocessor.SetListingsProvider(ddSource);
    91121    ddprocessor.SetUserID(source.userid);
    92122    ddprocessor.SetPassword(source.password);
     
    251281
    252282    if (xmltv_grabber == "datadirect")
    253283        return grabDDData(source, offset, *qCurrentDate, DD_ZAP2IT);
     284    if (xmltv_grabber == "schedulesdirect1")
     285        return grabDDData(source, offset, *qCurrentDate, DD_SCHEDULES_DIRECT);
    254286
    255287    char tempfilename[] = "/tmp/mythXXXXXX";
    256288    if (mkstemp(tempfilename) == -1)
     
    389421bool FillData::fillData(QValueList<Source> &sourcelist)
    390422{
    391423    QValueList<Source>::Iterator it;
     424    QValueList<Source>::Iterator it2;
    392425
    393426    QString status, querystr;
    394427    MSqlQuery query(MSqlQuery::InitCon());
     
    402435
    403436    need_post_grab_proc = false;
    404437    int nonewdata = 0;
     438    bool has_dd_source = false;
    405439
     440    // find all DataDirect duplicates, so we only data download once.
    406441    for (it = sourcelist.begin(); it != sourcelist.end(); ++it)
    407442    {
     443        if (!is_grabber_datadirect((*it).xmltvgrabber))
     444            continue;
    408445
     446        has_dd_source = true;
     447        for (it2 = sourcelist.begin(); it2 != sourcelist.end(); ++it2)
     448        {
     449            if (((*it).id           != (*it2).id)           &&
     450                ((*it).xmltvgrabber == (*it2).xmltvgrabber) &&
     451                ((*it).userid       == (*it2).userid)       &&
     452                ((*it).password     == (*it2).password))
     453            {
     454                (*it).dd_dups.push_back((*it2).id);
     455            }
     456        }
     457    }
     458    if (has_dd_source)
     459        ddprocessor.CreateTempDirectory();
     460
     461    for (it = sourcelist.begin(); it != sourcelist.end(); ++it)
     462    {
     463
    409464        query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c "
    410465                      "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID "
    411466                      "AND manualid = 0;");
     
    427482
    428483        if (xmltv_grabber == "eitonly")
    429484        {
    430             VERBOSE(VB_IMPORTANT, "Source configured to use only the "
    431                     "broadcasted guide data. Skipping.");
     485            VERBOSE(VB_GENERAL,
     486                    QString("Source %1 configured to use only the "
     487                            "broadcasted guide data. Skipping.")
     488                    .arg((*it).id));
     489
    432490            externally_handled++;
    433491            query.exec(QString("UPDATE settings SET data ='%1' "
    434492                               "WHERE value='mythfilldatabaseLastRunStart' OR "
     
    440498                 xmltv_grabber == "none" ||
    441499                 xmltv_grabber == "")
    442500        {
    443             VERBOSE(VB_IMPORTANT,
    444                     "Source configured with no grabber. Nothing to do.");
     501            VERBOSE(VB_GENERAL,
     502                    QString("Source %1 configured with no grabber. "
     503                            "Nothing to do.").arg((*it).id));
     504
    445505            externally_handled++;
    446506            query.exec(QString("UPDATE settings SET data ='%1' "
    447507                               "WHERE value='mythfilldatabaseLastRunStart' OR "
     
    486546
    487547        bool hasprefmethod = false;
    488548
    489         if (xmltv_grabber != "datadirect")
     549        if (is_grabber_external(xmltv_grabber))
    490550        {
    491551
    492552            QProcess grabber_capabilities_proc(xmltv_grabber);
     
    584644            }
    585645        }
    586646
    587         need_post_grab_proc |= (xmltv_grabber != "datadirect");
     647        need_post_grab_proc |= !is_grabber_datadirect(xmltv_grabber);
    588648
    589         if ((xmltv_grabber == "datadirect") && dd_grab_all)
     649        if (is_grabber_labs(xmltv_grabber) && dd_grab_all)
    590650        {
    591651            if (only_update_channels)
    592652                DataDirectUpdateChannels(*it);
     
    601661            if (!grabData(*it, 0))
    602662                ++failures;
    603663        }
    604         else if ((*it).xmltvgrabber_baseline || xmltv_grabber == "datadirect")
     664        else if ((*it).xmltvgrabber_baseline ||
     665                 is_grabber_datadirect(xmltv_grabber))
    605666        {
    606667
    607668            QDate qCurrentDate = QDate::currentDate();
     
    612673
    613674            if (maxDays > 0) // passed with --max-days
    614675                grabdays = maxDays;
    615             else if (xmltv_grabber == "datadirect")
     676            else if (is_grabber_datadirect(xmltv_grabber))
    616677                grabdays = 14;
    617678
    618679            grabdays = (only_update_channels) ? 1 : grabdays;
     
    620681            if (grabdays == 1)
    621682                refresh_today = true;
    622683
    623             if ((xmltv_grabber == "datadirect") && only_update_channels)
     684            if (is_grabber_labs(xmltv_grabber) && only_update_channels)
    624685            {
    625686                DataDirectUpdateChannels(*it);
    626687                grabdays = 0;
  • programs/mythfilldatabase/main.cpp

     
    1616// libmythtv headers
    1717#include "scheduledrecording.h"
    1818#include "remoteutil.h"
     19#include "videosource.h" // for is_grabber..
    1920
    2021// filldata headers
    2122#include "filldata.h"
     
    3435    bool from_file = false;
    3536    bool mark_repeats = true;
    3637
    37     bool usingDataDirect = false;
     38    bool usingDataDirect = false, usingDataDirectLabs = false;
    3839    bool grab_data = true;
    3940
    4041    bool export_iconmap = false;
     
    579580                       newsource.xmltvgrabber_prefmethod = "";
    580581
    581582                       sourcelist.append(newsource);
    582                        if (newsource.xmltvgrabber == "datadirect")
    583                            usingDataDirect = true;
     583                       usingDataDirect |=
     584                           is_grabber_datadirect(newsource.xmltvgrabber);
     585                       usingDataDirectLabs |=
     586                           is_grabber_labs(newsource.xmltvgrabber);
    584587                  }
    585588             }
    586589             else
     
    814817        fill_data.ddprocessor.GrabNextSuggestedTime();
    815818    }
    816819
     820    if (usingDataDirectLabs ||
     821        !gContext->GetNumSetting("MythFillFixProgramIDsHasRunOnce", 0))
     822    {
     823        DataDirectProcessor::FixProgramIDs();
     824    }
     825
    817826    VERBOSE(VB_GENERAL, "\n"
    818827            "===============================================================\n"
    819828            "| Attempting to contact the master backend for rescheduling.  |\n"
  • programs/mythfilldatabase/filldata.h

     
    2626    bool    xmltvgrabber_manualconfig;
    2727    bool    xmltvgrabber_cache;
    2828    QString xmltvgrabber_prefmethod;
     29    vector<int> dd_dups;
    2930};
    3031
    3132class FillData