Ticket #6322: 137-editgrid.fixes.code.5.patch

File 137-editgrid.fixes.code.5.patch, 104.8 KB (added by anonymous, 17 years ago)
  • mythtv/libs/libmyth/mythdialogs.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/mythdialogs.cpp release.20115.0305gridedit/mythtv/libs/libmyth/mythdialogs.cpp
     
    12581258        rect_to_update = this->geometry();
    12591259    }
    12601260
    1261     redrawRect = redrawRect.unite(r);
     1261    redrawRect = redrawRect.unite(rect_to_update);
    12621262
    12631263    update(redrawRect);
    12641264}
     
    16001600    return GetUIType<UIBlackHoleType>(this, name);
    16011601}
    16021602
     1603UIGridEditImageType* MythThemedDialog::getUIGridEditImageType(const QString &name)
     1604{
     1605    return GetUIType<UIGridEditImageType>(this, name);
     1606}
     1607
     1608UIGridEditSliderType* MythThemedDialog::getUIGridEditSliderType(const QString &name)
     1609{
     1610    return GetUIType<UIGridEditSliderType>(this, name);
     1611}
     1612
    16031613UIImageType* MythThemedDialog::getUIImageType(const QString &name)
    16041614{
    16051615    return GetUIType<UIImageType>(this, name);
  • mythtv/libs/libmyth/mythdialogs.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/mythdialogs.h release.20115.0305gridedit/mythtv/libs/libmyth/mythdialogs.h
     
    3333class UICheckBoxType;
    3434class UISelectorType;
    3535class UIBlackHoleType;
     36class UIGridEditImageType;
     37class UIGridEditSliderType;
    3638class UIImageType;
    3739class UIImageGridType;
    3840class UIStatusBarType;
     
    373375    UICheckBoxType *getUICheckBoxType(const QString &name);
    374376    UISelectorType *getUISelectorType(const QString &name);
    375377    UIBlackHoleType *getUIBlackHoleType(const QString &name);
     378    UIGridEditImageType *getUIGridEditImageType(const QString &name);
     379    UIGridEditSliderType *getUIGridEditSliderType(const QString &name);
    376380    UIImageGridType *getUIImageGridType(const QString &name);
    377381    UIImageType *getUIImageType(const QString &name);
    378382    UIStatusBarType *getUIStatusBarType(const QString &name);
  • mythtv/libs/libmyth/uitypes.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/uitypes.cpp release.20115.0305gridedit/mythtv/libs/libmyth/uitypes.cpp
     
    53385338
    53395339// ********************************************************************
    53405340
     5341UIGridEditImageType::UIGridEditImageType(const QString &name)
     5342                     : UIType(name)
     5343{
     5344    cutStatus = 0;
     5345    highlightFrame = false; // Used to highlight frame #0
     5346    framenumber = -1;
     5347}
     5348
     5349void UIGridEditImageType::calculateScreenArea()
     5350{
     5351    QRect r = area;
     5352    r.moveBy(m_parent->GetAreaRect().left(),
     5353             m_parent->GetAreaRect().top());
     5354    screen_area = r;
     5355
     5356    inner_border.setLeft(screen_area.left()+1);
     5357    inner_border.setRight(screen_area.right()-1);
     5358    inner_border.setTop(screen_area.top()+1);
     5359    inner_border.setBottom(screen_area.bottom()-1);
     5360
     5361    outer_border = screen_area;
     5362}
     5363
     5364void UIGridEditImageType::Draw(QPainter *p, int drawlayer, int context)
     5365{
     5366    if (pmap.isNull())
     5367    {
     5368        QColor drawcolor = QColor( 0, 0, 0);
     5369        p->setBrush(QBrush(Qt::SolidPattern));
     5370        p->setPen(QPen(drawcolor, 2));
     5371        p->drawRect(screen_area);
     5372    }
     5373    else
     5374    {
     5375        p->drawPixmap(screen_area, pmap);
     5376
     5377        p->setBrush(QBrush(Qt::NoBrush));
     5378        // Draw the frame outline
     5379        // This may be covered by the cut indicator
     5380        // Or the highlight
     5381 
     5382        p->setPen(QPen(colorSet[0], 3));
     5383        p->drawRect(outer_border);
     5384
     5385        if (cutStatus > 0)
     5386        {
     5387            p->setPen(QPen(colorSet[cutStatus], 3));
     5388            p->drawRect(inner_border);
     5389            p->drawLine(inner_border.topLeft(), inner_border.bottomRight());
     5390            p->drawLine(inner_border.bottomLeft(), inner_border.topRight());
     5391        }
     5392        if (highlightFrame)
     5393        {
     5394            // Overlay the image frame with the standard frame color
     5395            // This is used to highlight small frame #0
     5396            p->setPen(QPen(highlightColor, 3));
     5397            p->drawRect(outer_border);
     5398        }
     5399    }
     5400}
     5401
     5402void UIGridEditImageType::setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus)
     5403{
     5404    // We can get a null new_pmap at the start or end of the video
     5405    if (! new_pmap)
     5406    {
     5407        clearPixmap();
     5408        return;
     5409    }
     5410
     5411    if (frame == framenumber)
     5412    {
     5413        // No change in pixmap (?)
     5414        setCutStatus(new_cutStatus);
     5415        return;
     5416    }
     5417
     5418    pmap = *new_pmap;
     5419    framenumber = frame;
     5420
     5421    if (new_cutStatus >= 0 && new_cutStatus <= 3)
     5422        cutStatus = new_cutStatus;
     5423    else
     5424        cutStatus = 0;
     5425
     5426    refresh();
     5427}
     5428
     5429void UIGridEditImageType::clearPixmap(bool dorefresh)
     5430{
     5431    if (! pmap.isNull())
     5432    {
     5433        pmap = QPixmap();
     5434
     5435        cutStatus = 0;
     5436        framenumber = -1;
     5437        if (dorefresh)
     5438            refresh();
     5439    }
     5440}
     5441
     5442void UIGridEditImageType::setCutStatus(int new_cutStatus)
     5443{
     5444    if (new_cutStatus == cutStatus)
     5445        return;
     5446
     5447    if (new_cutStatus >= 0 && new_cutStatus <= 3)
     5448        cutStatus = new_cutStatus;
     5449    else
     5450        cutStatus = 0;
     5451
     5452    refresh();
     5453}
     5454
     5455// ********************************************************************
     5456
     5457UIGridEditSliderType::UIGridEditSliderType(const QString &name)
     5458                     : UIType(name)
     5459{
     5460    m_drawMap = NULL;
     5461    m_position=0;
     5462}
     5463
     5464void UIGridEditSliderType::calculateScreenArea()
     5465{
     5466    QRect r = area;
     5467    r.moveBy(m_parent->GetAreaRect().left(),
     5468             m_parent->GetAreaRect().top());
     5469    screen_area = r;
     5470
     5471    if (m_drawMap)
     5472        delete [] m_drawMap;
     5473
     5474    m_drawWidth = area.width();
     5475    m_drawMap = new unsigned char[m_drawWidth];
     5476    for (int i = 0; i < m_drawWidth; i++)
     5477        m_drawMap[i] = 0;
     5478}
     5479
     5480void UIGridEditSliderType::ClearAll()
     5481{
     5482    for (int i = 0; i < m_drawWidth; i++)
     5483        m_drawMap[i] = 0;
     5484    refresh();
     5485}
     5486
     5487void UIGridEditSliderType::SetRange(
     5488        long long fstart, long long fend, long long fcount)
     5489{
     5490    if (fcount <= 0)
     5491    {
     5492        VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1")
     5493                .arg(fcount));
     5494        return;
     5495    }
     5496    if (fstart < 0)
     5497    {
     5498        VERBOSE(VB_IMPORTANT, QString("Invalid starting frame: %1")
     5499                .arg(fstart));
     5500        return;
     5501    }
     5502    if (fend < 0)
     5503    {
     5504        VERBOSE(VB_IMPORTANT, QString("Invalid ending frame: %1")
     5505                .arg(fend));
     5506        return;
     5507    }
     5508
     5509    if (fstart > fcount) fstart = fcount;
     5510    if (fend > fcount) fend = fcount;
     5511
     5512    int start = (int)((1.0 * fstart * m_drawWidth) / fcount);
     5513    int end   = (int)((1.0 * fend   * m_drawWidth) / fcount);
     5514
     5515    if (start < 0)
     5516        start = 0;
     5517    if (start >= m_drawWidth)
     5518        start = m_drawWidth - 1;
     5519    if (end < 0)
     5520        end = 0;
     5521    if (end >= m_drawWidth)
     5522        end = m_drawWidth - 1;
     5523
     5524    if (end < start)
     5525    {
     5526        int tmp = start;
     5527        start = end;
     5528        end = tmp;
     5529    }
     5530
     5531    for (int i = start; i < end; i++)
     5532        if (m_drawMap[i] < 1)
     5533            m_drawMap[i] = 1;
     5534
     5535    // Mark endpoints
     5536    m_drawMap[start] = 2;
     5537    m_drawMap[end]   = 2;
     5538
     5539    VERBOSE(VB_GENERAL, QString("Range = %1 - %2 (%3 - %4)")
     5540            .arg(start).arg(end)
     5541            .arg(fstart).arg(fend));
     5542    refresh();
     5543}
     5544
     5545void UIGridEditSliderType::SetPosition(
     5546        long long fposition, long long fcount)
     5547{
     5548    if (fcount <= 0)
     5549    {
     5550        VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1")
     5551                .arg(fcount));
     5552        return;
     5553    }
     5554
     5555    if (fposition < 0)
     5556    {
     5557        VERBOSE(VB_IMPORTANT, QString("Invalid position frame: %1")
     5558                .arg(fposition));
     5559        return;
     5560    }
     5561
     5562    if (fposition > fcount) fposition = fcount;
     5563
     5564    int new_position = (int)(1.0 * fposition * m_drawWidth) / fcount;
     5565
     5566    if (new_position < 0)
     5567        new_position = 0;
     5568    if (new_position >= m_drawWidth)
     5569       new_position = m_drawWidth - 1;
     5570
     5571    if (new_position != m_position)
     5572    {
     5573        m_position = new_position;
     5574        refresh();
     5575    }
     5576}
     5577
     5578void UIGridEditSliderType::Draw(QPainter *p, int drawlayer, int context)
     5579{
     5580    // Draw Background
     5581    p->setPen(QPen(colorSet[0], 2));
     5582    p->setBrush(colorSet[0]);
     5583    p->drawRect(screen_area);
     5584
     5585    // Draw bars
     5586
     5587//    VERBOSE(VB_GENERAL, QString("Starting"));
     5588    int i = 0;
     5589    do {
     5590        int start = 0;
     5591        int end = 0;
     5592
     5593        while (i < m_drawWidth && m_drawMap[i] == 0) i++;
     5594        if (i == m_drawWidth) break;
     5595        start = i;
     5596
     5597        i++;
     5598       
     5599
     5600        while (i < m_drawWidth && m_drawMap[i] == 1) i++;
     5601        end = i;
     5602        if (end == m_drawWidth) end--;
     5603
     5604        // If the next map value is not a normal internal cutpoint
     5605        // increment i so we handle it properly
     5606        if (end+1 < m_drawWidth && m_drawMap[end+1] != 1)
     5607            i++;
     5608
     5609        // start == starting point
     5610        //   end == endingpoint
     5611        {
     5612            QRect r = screen_area;
     5613            r.setLeft(r.left() + start);
     5614            r.setWidth(end - start);
     5615
     5616//            VERBOSE(VB_GENERAL, QString("Cut from (%1, %2) - (%3, %4)")
     5617//                    .arg(r.left()).arg(r.top())
     5618//                    .arg(r.right()).arg(r.bottom()));
     5619
     5620//            VERBOSE(VB_GENERAL, QString("start = %1, m_position = %2, end = %3")
     5621//                    .arg(start)
     5622//                    .arg(m_position)
     5623//                    .arg(end));
     5624           
     5625            if (start <= m_position && m_position <= end)
     5626            {
     5627                p->setPen(QPen(colorSet[4], 2));
     5628                p->setBrush(colorSet[4]);
     5629            }
     5630            else
     5631            {
     5632                p->setPen(QPen(colorSet[1], 2));
     5633                p->setBrush(colorSet[1]);
     5634            }
     5635            p->drawRect(r);
     5636
     5637            p->setPen(QPen(colorSet[2], 2));
     5638            p->setBrush(colorSet[2]);
     5639            if (m_drawMap[start] == 2)
     5640                p->drawLine(r.topLeft(), r.bottomLeft());
     5641            if (m_drawMap[end] == 2)
     5642                p->drawLine(r.topRight(), r.bottomRight());
     5643
     5644        }
     5645    } while (i < m_drawWidth);
     5646
     5647    // Draw Current Position Mark
     5648
     5649    QPoint ptop(screen_area.left() + m_position, screen_area.top());
     5650    QPoint pbot(screen_area.left() + m_position, screen_area.bottom());
     5651
     5652    p->setPen(QPen(colorSet[3], 2));
     5653    p->setBrush(colorSet[3]);
     5654    p->drawLine(ptop, pbot);
     5655}
     5656
     5657// ********************************************************************
     5658
    53415659UIKeyType::UIKeyType(const QString &name)
    53425660         : UIType(name)
    53435661{
  • mythtv/libs/libmyth/uitypes.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/uitypes.h release.20115.0305gridedit/mythtv/libs/libmyth/uitypes.h
     
    13851385    QRect area;
    13861386};
    13871387
     1388class MPUBLIC UIGridEditImageType : public UIType
     1389{
     1390    Q_OBJECT
     1391
     1392  public:
     1393
     1394    UIGridEditImageType(const QString &name);
     1395    void calculateScreenArea();
     1396    void setArea(QRect an_area)     { area = an_area; };
     1397
     1398    void setOutlineColor(QColor c)  { colorSet[0] = c; };
     1399    void setCutColor(QColor c)      { colorSet[1] = c; };
     1400    void setCutPointColor(QColor c)
     1401    {
     1402         colorSet[2] = c; // Cut before
     1403         colorSet[3] = c; // Cut after
     1404    };
     1405    void setHighlightFrame(bool high) { highlightFrame = high; };
     1406    void setHighlightColor(QColor c)  { highlightColor = c; };
     1407
     1408    virtual void Draw(QPainter *, int, int);
     1409    void setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus);
     1410 
     1411    void clearPixmap(bool dorefresh=true);
     1412    void setCutStatus(int new_cutStatus);
     1413
     1414    QRect getOuterBorder() { return outer_border; };
     1415  protected:
     1416
     1417    QRect    area;
     1418    QRect    inner_border;
     1419    QRect    outer_border;
     1420    QPixmap  pmap;
     1421    long long framenumber; // for consistency checking
     1422    int      cutStatus;
     1423    QColor   colorSet[4];
     1424    bool     highlightFrame;
     1425    QColor   highlightColor;
     1426};
     1427
     1428class MPUBLIC UIGridEditSliderType : public UIType
     1429{
     1430    Q_OBJECT
     1431
     1432  public:
     1433
     1434    UIGridEditSliderType(const QString &name);
     1435    void calculateScreenArea();
     1436    void setArea(QRect an_area)     { area = an_area; };
     1437
     1438    void setFillColor(QColor c)     { colorSet[0] = c; };
     1439    void setCutColor(QColor c)      { colorSet[1] = c; };
     1440    void setCutPointColor(QColor c) { colorSet[2] = c; };
     1441    void setPositionColor(QColor c) { colorSet[3] = c; };
     1442    void setInCutColor(QColor c)    { colorSet[4] = c; };
     1443
     1444    void ClearAll();
     1445    void SetRange(long long fstart, long long fend, long long fcount);
     1446    void SetPosition(long long fposition, long long fcount);
     1447
     1448    virtual void Draw(QPainter *, int, int);
     1449  protected:
     1450
     1451    QRect          area;
     1452    unsigned char *m_drawMap;
     1453    int            m_drawWidth;
     1454    int            m_position;
     1455
     1456    QColor         colorSet[5];
     1457};
     1458
     1459
    13881460class MPUBLIC UIKeyType : public UIType
    13891461{
    13901462    Q_OBJECT
  • mythtv/libs/libmyth/xmlparse.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/xmlparse.cpp release.20115.0305gridedit/mythtv/libs/libmyth/xmlparse.cpp
     
    1313#undef LoadImage
    1414#endif
    1515
     16#define LOC QString("XMLParse: ")
     17#define LOC_WARN QString("XMLParse, Warning: ")
     18#define LOC_ERR QString("XMLParse, Error: ")
     19
    1620MPUBLIC QMap<QString, fontProp> globalFontMap;
    1721
    1822XMLParse::XMLParse(void)
     
    14421446            {
    14431447                parseBlackHole(container, info);
    14441448            }
     1449            else if (info.tagName() == "grideditimage")
     1450            {
     1451                parseGridEditImage(container, info);
     1452            }
     1453            else if (info.tagName() == "grideditslider")
     1454            {
     1455                parseGridEditSlider(container, info);
     1456            }
    14451457            else if (info.tagName() == "area")
    14461458            {
    14471459                area = parseRect(getFirstText(info));
     
    34453457    container->AddType(bh);
    34463458}
    34473459
     3460
     3461void XMLParse::parseGridEditImage(LayerSet *container, QDomElement &element)
     3462{
     3463    QRect area;
     3464    QColor outlineColor;
     3465    QColor cutColor;
     3466    QColor cutPointColor;
     3467    QColor highlightColor;
     3468    bool   haveOutlineColor = false;
     3469    bool   haveCutColor = false;
     3470    bool   haveCutPointColor = false;
     3471    bool   haveHighlightColor = false;
     3472    bool   highlightFrame = false;
     3473
     3474    QString name = element.attribute("name", "");
     3475    if (name.isNull() || name.isEmpty())
     3476    {
     3477        VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditImage needs a name");
     3478        return;
     3479    }
     3480    QString highlight = element.attribute("highlightframe", "");
     3481    if (highlight == "true")
     3482        highlightFrame = true;
     3483
     3484    for (QDomNode child = element.firstChild(); !child.isNull();
     3485         child = child.nextSibling())
     3486    {
     3487        QDomElement info = child.toElement();
     3488        if (!info.isNull())
     3489        {
     3490            if (info.tagName() == "area")
     3491            {
     3492                area = parseRect(getFirstText(info));
     3493                normalizeRect(area);
     3494            }
     3495            else if (info.tagName() == "outlinecolor")
     3496            {
     3497                haveOutlineColor = true;
     3498                outlineColor = getFirstText(info);
     3499            }
     3500            else if (info.tagName() == "cutcolor")
     3501            {
     3502                haveCutColor = true;
     3503                cutColor = getFirstText(info);
     3504            }
     3505            else if (info.tagName() == "cutpointcolor")
     3506            {
     3507                haveCutPointColor = true;
     3508                cutPointColor = getFirstText(info);
     3509            }
     3510            else if (info.tagName() == "highlightcolor")
     3511            {
     3512                haveHighlightColor = true;
     3513                highlightColor = getFirstText(info);
     3514            }
     3515            else
     3516            {
     3517                VERBOSE(VB_IMPORTANT, LOC_WARN +
     3518                        QString("Unknown tag '%1' in grideditimage '%2'")
     3519                        .arg(info.tagName()).arg(name));
     3520                return;
     3521            }
     3522        }
     3523    }
     3524
     3525    if (!haveOutlineColor)
     3526    {
     3527        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3528                QString("Missing tag 'outlinecolor' in grideditimage '%1'")
     3529                .arg(name));
     3530        return;
     3531    }
     3532
     3533    if (!haveCutColor)
     3534    {
     3535        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3536                QString("Missing tag 'cutcolor' in grideditimage '%1'")
     3537                .arg(name));
     3538        return;
     3539    }
     3540
     3541    if (!haveCutPointColor)
     3542    {
     3543        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3544                QString("Missing tag 'cutpointcolor' in grideditimage '%1'")
     3545                .arg(name));
     3546        return;
     3547    }
     3548
     3549    if (highlightFrame && !haveHighlightColor)
     3550    {
     3551        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3552                QString("highlightframe specified but missing tag 'hightlightcolor' in grideditimage '%1'")
     3553                .arg(name));
     3554        return;
     3555    }
     3556
     3557
     3558    UIGridEditImageType *gei = new UIGridEditImageType(name);
     3559    gei->SetScreen(wmult, hmult);
     3560    gei->setArea(area);
     3561    gei->setOutlineColor(outlineColor);
     3562    gei->setCutColor(cutColor);
     3563    gei->setCutPointColor(cutPointColor);
     3564    gei->setHighlightColor(highlightColor);
     3565    gei->setHighlightFrame(highlightFrame);
     3566    gei->SetParent(container);
     3567    gei->calculateScreenArea();
     3568    gei->clearPixmap(false);
     3569    container->AddType(gei);
     3570}
     3571
     3572void XMLParse::parseGridEditSlider(LayerSet *container, QDomElement &element)
     3573{
     3574    QRect area;
     3575    QColor fillColor;
     3576    QColor cutColor;
     3577    QColor inCutColor;
     3578    QColor cutPointColor;
     3579    QColor positionColor;
     3580    bool   haveFillColor = false;
     3581    bool   haveCutColor = false;
     3582    bool   haveInCutColor = false;
     3583    bool   haveCutPointColor = false;
     3584    bool   havePositionColor = false;
     3585
     3586    QString name = element.attribute("name", "");
     3587    if (name.isNull() || name.isEmpty())
     3588    {
     3589        VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditSlider needs a name");
     3590        return;
     3591    }
     3592
     3593    for (QDomNode child = element.firstChild(); !child.isNull();
     3594         child = child.nextSibling())
     3595    {
     3596        QDomElement info = child.toElement();
     3597        if (!info.isNull())
     3598        {
     3599            if (info.tagName() == "area")
     3600            {
     3601                area = parseRect(getFirstText(info));
     3602                normalizeRect(area);
     3603            }
     3604            else if (info.tagName() == "fillcolor")
     3605            {
     3606                haveFillColor = true;
     3607                fillColor = getFirstText(info);
     3608            }
     3609            else if (info.tagName() == "cutcolor")
     3610            {
     3611                haveCutColor = true;
     3612                cutColor = getFirstText(info);
     3613            }
     3614            else if (info.tagName() == "incutcolor")
     3615            {
     3616                haveInCutColor = true;
     3617                inCutColor = getFirstText(info);
     3618            }
     3619            else if (info.tagName() == "cutpointcolor")
     3620            {
     3621                haveCutPointColor = true;
     3622                cutPointColor = getFirstText(info);
     3623            }
     3624            else if (info.tagName() == "positioncolor")
     3625            {
     3626                havePositionColor = true;
     3627                positionColor = getFirstText(info);
     3628            }
     3629            else
     3630            {
     3631                VERBOSE(VB_IMPORTANT, LOC_WARN +
     3632                        QString("Unknown tag '%1' in grideditslider '%2'")
     3633                        .arg(info.tagName()).arg(name));
     3634                return;
     3635            }
     3636        }
     3637    }
     3638
     3639    if (!haveFillColor)
     3640    {
     3641        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3642                QString("Missing tag 'fillcolor' in grideditslider '%1'")
     3643                .arg(name));
     3644        return;
     3645    }
     3646
     3647    if (!haveCutColor)
     3648    {
     3649        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3650                QString("Missing tag 'cutcolor' in grideditslider '%1'")
     3651                .arg(name));
     3652        return;
     3653    }
     3654
     3655    if (!haveInCutColor)
     3656    {
     3657        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3658                QString("Missing tag 'incutcolor' in grideditslider '%1'")
     3659                .arg(name));
     3660        return;
     3661    }
     3662
     3663    if (!haveCutPointColor)
     3664    {
     3665        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3666                QString("Missing tag 'cutpointcolor' in grideditslider '%1'")
     3667                .arg(name));
     3668        return;
     3669    }
     3670
     3671    if (!havePositionColor)
     3672    {
     3673        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3674                QString("Missing tag 'positioncolor' in grideditslider '%1'")
     3675                .arg(name));
     3676        return;
     3677    }
     3678
     3679    UIGridEditSliderType *ges = new UIGridEditSliderType(name);
     3680    ges->SetScreen(wmult, hmult);
     3681    ges->setArea(area);
     3682    ges->setFillColor(fillColor);
     3683    ges->setCutColor(cutColor);
     3684    ges->setInCutColor(inCutColor);
     3685    ges->setCutPointColor(cutPointColor);
     3686    ges->setPositionColor(positionColor);
     3687    ges->SetParent(container);
     3688    ges->calculateScreenArea();
     3689    container->AddType(ges);
     3690}
     3691
    34483692void XMLParse::parseListBtnArea(LayerSet *container, QDomElement &element)
    34493693{
    34503694    int context = -1;
  • mythtv/libs/libmyth/xmlparse.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/xmlparse.h release.20115.0305gridedit/mythtv/libs/libmyth/xmlparse.h
     
    4949    void parseCheckBox(LayerSet *, QDomElement &);
    5050    void parseSelector(LayerSet *, QDomElement &);
    5151    void parseBlackHole(LayerSet *, QDomElement &);
     52    void parseGridEditImage(LayerSet *, QDomElement &);
     53    void parseGridEditSlider(LayerSet *, QDomElement &);
    5254    void parseListBtnArea(LayerSet *, QDomElement &);
    5355    void parseListTreeArea(LayerSet *, QDomElement &);
    5456    void parseKeyboard(LayerSet *, QDomElement &);
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
     
    5353#include "interactivetv.h"
    5454#include "util-osx-cocoa.h"
    5555
     56#include "grideditcutpoints.h"
     57
    5658extern "C" {
    5759#include "vbitext/vbi.h"
    5860#include "vsync.h"
     
    157159      decoder_thread_alive(true),   killplayer(false),
    158160      killvideo(false),             livetv(false),
    159161      watchingrecording(false),     editmode(false),
     162      hideedits(false),
    160163      resetvideo(false),            using_null_videoout(false),
    161164      no_audio_in(false),           no_audio_out(false),
    162165      transcoding(false),
     
    166169      bookmarkseek(0),              previewFromBookmark(false),
    167170      // Seek
    168171      fftime(0),                    seekamountpos(4),
    169       seekamount(30),               exactseeks(false),
     172      allow_pagesize(false),        half_page(0),
     173      seekamount(30),               seekamounttext("30 Frames"),
     174      exactseeks(false),
    170175      // Playback misc.
    171176      videobuf_retries(0),          framesPlayed(0),
    172177      totalFrames(0),               totalLength(0),
     
    218223      yuv_need_copy(false),         yuv_desired_size(0,0),
    219224      yuv_scaler(NULL),             yuv_frame_scaled(NULL),
    220225      yuv_scaler_in_size(0,0),      yuv_scaler_out_size(0,0),
     226      // Grid Editing
     227      grid_edit_image_scaler(NULL), grid_edit_image_small_scaler(NULL),
     228      grid_edit_image_buffer_yuv(NULL), grid_edit_image_small_buffer_yuv(NULL),
     229      grid_edit_image_buffer_rgb(NULL), grid_edit_image_small_buffer_rgb(NULL),
     230      grid_edit_image_buffer_length(0), grid_edit_image_small_buffer_length(0),
     231      grid_edit_image_in_size(-1, -1),
     232
    221233      // Filters
    222234      videoFiltersForProgram(""),   videoFiltersOverride(""),
    223235      postfilt_width(0),            postfilt_height(0),
     
    388400        output_jmeter = NULL;
    389401    }
    390402
     403    ClearScreenGrab();
     404
    391405    ShutdownYUVResize();
    392406}
    393407
     
    15261540    return retval;
    15271541}
    15281542
     1543
     1544bool NuppelVideoPlayer::GetScreenGrabsOfCurrentFrame(QImage &normal, QImage &small)
     1545{
     1546
     1547    unsigned char *data      = NULL;
     1548    VideoFrame    *frame     = NULL;
     1549    AVPicture      orig;
     1550    AVPicture      scaled;
     1551    AVPicture      scaled_small;
     1552    bzero(&orig,         sizeof(AVPicture));
     1553    bzero(&scaled,       sizeof(AVPicture));
     1554    bzero(&scaled_small, sizeof(AVPicture));
     1555
     1556    int vw, vh;
     1557    if (!(frame = GetCurrentFrame(vw, vh)))
     1558    {
     1559        return false;
     1560    }
     1561
     1562    if (!(data = frame->buf))
     1563    {
     1564        ReleaseCurrentFrame(frame);
     1565        return false;;
     1566    }
     1567
     1568    // Check to see if the screen dimensions have changed
     1569    // Probably shouldn't happen in normal use.
     1570    if (grid_edit_image_in_size != video_dim)
     1571        SetupScreenGrab();
     1572
     1573    avpicture_fill(&orig, data, PIX_FMT_YUV420P,
     1574                   video_dim.width(), video_dim.height());
     1575
     1576    avpicture_deinterlace(&orig, &orig, PIX_FMT_YUV420P,
     1577                          video_dim.width(), video_dim.height());
     1578
     1579    // Rescale to the normal size
     1580    avpicture_fill(&scaled, grid_edit_image_buffer_yuv, PIX_FMT_YUV420P,
     1581                   grid_edit_image_size.width(),
     1582                   grid_edit_image_size.height());
     1583
     1584    img_resample(grid_edit_image_scaler, &scaled, &orig);
     1585
     1586    // Don't need the current frame anymore so release it
     1587    ReleaseCurrentFrame(frame);
     1588
     1589    // Rescale to the small size
     1590    avpicture_fill(&scaled_small, grid_edit_image_small_buffer_yuv, PIX_FMT_YUV420P,
     1591                   grid_edit_image_small_size.width(),
     1592                   grid_edit_image_small_size.height());
     1593
     1594    img_resample(grid_edit_image_small_scaler, &scaled_small, &scaled);
     1595
     1596    // Convert scaled and scaled_small from YUV to RGB
     1597
     1598    // scaled first
     1599    uint w = grid_edit_image_size.width();
     1600    uint h = grid_edit_image_size.height();
     1601    unsigned char *yuv_buf = grid_edit_image_buffer_yuv;
     1602    unsigned char *rgb_buf = grid_edit_image_buffer_rgb;
     1603    yuv2argb_conv(rgb_buf,
     1604                  yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
     1605                  w, h, w * 4, w, w / 2, 0);
     1606
     1607    // scaled_small next
     1608    w = grid_edit_image_small_size.width();
     1609    h = grid_edit_image_small_size.height();
     1610    yuv_buf = grid_edit_image_small_buffer_yuv;
     1611    rgb_buf = grid_edit_image_small_buffer_rgb;
     1612    yuv2argb_conv(rgb_buf,
     1613                  yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
     1614                  w, h, w * 4, w, w / 2, 0);
     1615
     1616#ifdef MMX
     1617#define _RGBSWAP .swapRGB()
     1618#endif
     1619
     1620    normal = QImage(grid_edit_image_buffer_rgb,
     1621                    grid_edit_image_size.width(), grid_edit_image_size.height(),
     1622                    32, NULL, 65536 * 65536, QImage::LittleEndian)_RGBSWAP;
     1623
     1624    small = QImage(grid_edit_image_small_buffer_rgb,
     1625                   grid_edit_image_small_size.width(), grid_edit_image_small_size.height(),
     1626                   32, NULL, 65536 * 65536, QImage::LittleEndian)_RGBSWAP;
     1627
     1628    return true;
     1629}
     1630
    15291631void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame)
    15301632{
    15311633    if (frame)
     
    29263028    }
    29273029}
    29283030
     3031void NuppelVideoPlayer::SetScreenGrabSizes(QSize normal, QSize small)
     3032{
     3033    grid_edit_image_size = normal;
     3034    grid_edit_image_small_size = small;
     3035
     3036    SetupScreenGrab();
     3037    VERBOSE(VB_GENERAL, QString("Main Image = (%1, %2) from (%3, %4)")
     3038                        .arg(grid_edit_image_size.width())
     3039                        .arg(grid_edit_image_size.height())
     3040                        .arg(normal.width()).arg(normal.height()));
     3041    VERBOSE(VB_GENERAL, QString("Small Image = (%1, %2) from (%3, %4)")
     3042                        .arg(grid_edit_image_small_size.width())
     3043                        .arg(grid_edit_image_small_size.height())
     3044                        .arg(small.width()).arg(small.height()));
     3045
     3046}
     3047
     3048void NuppelVideoPlayer::ClearScreenGrab()
     3049{
     3050    if (grid_edit_image_scaler)
     3051    {
     3052        img_resample_close(grid_edit_image_scaler);
     3053        grid_edit_image_scaler = NULL;
     3054    }
     3055
     3056    if (grid_edit_image_small_scaler)
     3057    {
     3058        img_resample_close(grid_edit_image_small_scaler);
     3059        grid_edit_image_small_scaler=NULL;
     3060    }
     3061
     3062    if (grid_edit_image_buffer_yuv)
     3063    {
     3064        delete grid_edit_image_buffer_yuv;
     3065        grid_edit_image_buffer_yuv=NULL;
     3066    }
     3067
     3068    if (grid_edit_image_small_buffer_yuv)
     3069    {
     3070        delete grid_edit_image_small_buffer_yuv;
     3071        grid_edit_image_small_buffer_yuv=NULL;
     3072    }
     3073
     3074    if (grid_edit_image_buffer_rgb)
     3075    {
     3076        delete grid_edit_image_buffer_rgb;
     3077        grid_edit_image_buffer_rgb=NULL;
     3078    }
     3079
     3080    if (grid_edit_image_small_buffer_rgb)
     3081    {
     3082        delete grid_edit_image_small_buffer_rgb;
     3083        grid_edit_image_small_buffer_rgb=NULL;
     3084    }
     3085}
     3086
     3087void NuppelVideoPlayer::SetupScreenGrab()
     3088{
     3089    ClearScreenGrab();
     3090    grid_edit_image_in_size = video_dim;
     3091
     3092    // Normalize the output sizes.
     3093    // This is necessary to preserve the aspect ratio
     3094
     3095    QSize tmpsize = grid_edit_image_size;
     3096    grid_edit_image_size =  video_dim;
     3097    grid_edit_image_size.scale(tmpsize, QSize::ScaleMin);
     3098
     3099    tmpsize = grid_edit_image_small_size;
     3100    grid_edit_image_small_size = video_dim;
     3101    grid_edit_image_small_size.scale(tmpsize, QSize::ScaleMin);
     3102
     3103    grid_edit_image_size = QSize(grid_edit_image_size.width() & ~0x7,
     3104                                 grid_edit_image_size.height() & ~0x7);
     3105    grid_edit_image_small_size = QSize(grid_edit_image_small_size.width() & ~0x7,
     3106                                       grid_edit_image_small_size.height() & ~0x7);
     3107
     3108    // Do normal first
     3109    uint sz = grid_edit_image_size.width() * grid_edit_image_size.height();
     3110    grid_edit_image_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128];
     3111    grid_edit_image_buffer_rgb = new unsigned char[sz * 4 + 128];
     3112
     3113    grid_edit_image_scaler = img_resample_init(
     3114                grid_edit_image_size.width(), grid_edit_image_size.height(),
     3115                grid_edit_image_in_size.width(),  grid_edit_image_in_size.height());
     3116
     3117    // Then small
     3118    sz = grid_edit_image_small_size.width() * grid_edit_image_small_size.height();
     3119    grid_edit_image_small_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128];
     3120    grid_edit_image_small_buffer_rgb = new unsigned char[sz * 4 + 128];
     3121
     3122    // Resize from normal to small
     3123    grid_edit_image_small_scaler = img_resample_init(
     3124                grid_edit_image_small_size.width(), grid_edit_image_small_size.height(),
     3125                grid_edit_image_size.width(),  grid_edit_image_size.height());
     3126}
     3127
    29293128void NuppelVideoPlayer::DisplayNormalFrame(void)
    29303129{
    29313130    SetVideoActuallyPaused(false);
     
    49895188
    49905189    dialogname = "";
    49915190
     5191    osd->HideAllExcept("editmode");
     5192
    49925193    QMap<QString, QString> infoMap;
    49935194    m_playbackinfo->ToMap(infoMap);
    49945195    osd->SetText("editmode", infoMap, -1);
     
    50445245    m_playbackinfo->SetEditing(false);
    50455246}
    50465247
     5248bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame)
     5249{
     5250    bool tmpexactseeks = exactseeks;
     5251    GetDecoder()->setExactSeeks(true);
     5252
     5253//    VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2")
     5254//           .arg(GetFramesPlayed())
     5255//           .arg(targetFrame));
     5256
     5257    if (framesPlayed > targetFrame)
     5258    {
     5259        // seek back
     5260        rewindtime = framesPlayed - targetFrame;
     5261        while (rewindtime != 0)
     5262            usleep(1000);
     5263    }
     5264    else
     5265    {
     5266        // seek forward
     5267        fftime = targetFrame - framesPlayed;
     5268        while (fftime != 0)
     5269            usleep(1000);
     5270
     5271    }
     5272//    VERBOSE(VB_GENERAL, QString("After current frame = %1")
     5273//           .arg(GetFramesPlayed()));
     5274    GetDecoder()->setExactSeeks(tmpexactseeks);
     5275    return (targetFrame == framesPlayed);
     5276}
     5277
     5278void NuppelVideoPlayer::EditHandleClearMap()
     5279{
     5280    QMap<long long, int>::Iterator it;
     5281    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5282        osd->HideEditArrow(it.key(), it.data());
     5283
     5284    deleteMap.clear();
     5285    UpdateEditSlider();
     5286}
     5287
     5288void NuppelVideoPlayer::EditHandleInvertMap()
     5289{
     5290    QMap<long long, int>::Iterator it;
     5291    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5292        ReverseMark(it.key());
     5293
     5294    UpdateEditSlider();
     5295    UpdateTimeDisplay();
     5296}
     5297
     5298void NuppelVideoPlayer::EditHandleLoadCommSkip()
     5299{
     5300    if (hascommbreaktable)
     5301    {
     5302        commBreakMapLock.lock();
     5303        QMap<long long, int>::Iterator it;
     5304        for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it)
     5305        {
     5306            if (!deleteMap.contains(it.key()))
     5307            {
     5308                if (it.data() == MARK_COMM_START)
     5309                    AddMark(it.key(), MARK_CUT_START);
     5310                else
     5311                    AddMark(it.key(), MARK_CUT_END);
     5312            }
     5313        }
     5314        commBreakMapLock.unlock();
     5315        UpdateEditSlider();
     5316        UpdateTimeDisplay();
     5317    }
     5318}
     5319
    50475320bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e)
    50485321{
    50495322    bool handled = false;
     
    51235396            UpdateTimeDisplay();
    51245397        }
    51255398        else if (action == "CLEARMAP")
    5126         {
    5127             QMap<long long, int>::Iterator it;
    5128             for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
    5129                 osd->HideEditArrow(it.key(), it.data());
    5130 
    5131             deleteMap.clear();
    5132             UpdateEditSlider();
    5133         }
     5399            EditHandleClearMap();
    51345400        else if (action == "INVERTMAP")
    5135         {
    5136             QMap<long long, int>::Iterator it;
    5137             for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
    5138                 ReverseMark(it.key());
    5139 
    5140             UpdateEditSlider();
    5141             UpdateTimeDisplay();
    5142         }
     5401            EditHandleInvertMap();
    51435402        else if (action == "LOADCOMMSKIP")
    5144         {
    5145             if (hascommbreaktable)
    5146             {
    5147                 commBreakMapLock.lock();
    5148                 QMap<long long, int>::Iterator it;
    5149                 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it)
    5150                 {
    5151                     if (!deleteMap.contains(it.key()))
    5152                     {
    5153                         if (it.data() == MARK_COMM_START)
    5154                             AddMark(it.key(), MARK_CUT_START);
    5155                         else
    5156                             AddMark(it.key(), MARK_CUT_END);
    5157                     }
    5158                 }
    5159                 commBreakMapLock.unlock();
    5160                 UpdateEditSlider();
    5161                 UpdateTimeDisplay();
    5162             }
    5163         }
     5403            EditHandleLoadCommSkip();
    51645404        else if (action == "PREVCUT")
    51655405        {
    51665406            int old_seekamount = seekamount;
     
    52065446            UpdateEditSlider();
    52075447            UpdateTimeDisplay();
    52085448        }
    5209         else if (action == "ESCAPE" || action == "MENU" ||
    5210                  action == "TOGGLEEDIT")
     5449        else if (action == "TOGGLEEDIT" || action == "MENU")
     5450              m_tv->ShowEditRecordingGrid();
     5451        else if (action == "ESCAPE")
    52115452        {
    52125453            DisableEdit();
    52135454            retval = false;
     
    52205461    return retval;
    52215462}
    52225463
     5464void NuppelVideoPlayer::ShowEditRecordingGrid(void)
     5465{
     5466    // Completely hide the OSD
     5467    osd->HideAll();
     5468    hideedits = true;
     5469
     5470    GridEditCutpoints::Run(this);
     5471
     5472    ClearScreenGrab();
     5473
     5474    allow_pagesize = false;
     5475    hideedits = false;
     5476
     5477    // Show OSD
     5478
     5479    QMap<QString, QString> infoMap;
     5480    m_playbackinfo->ToMap(infoMap);
     5481    osd->SetText("editmode", infoMap, -1);
     5482
     5483    UpdateEditSlider();
     5484    UpdateTimeDisplay();
     5485    if (seekamountpos == 3 || seekamountpos == 4)
     5486        UpdateSeekAmount(true);
     5487    else
     5488        UpdateSeekAmountDisplay();
     5489
     5490    QMap<long long, int>::Iterator it;
     5491    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5492         AddMark(it.key(), it.data());
     5493}
     5494
    52235495AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const
    52245496{
    52255497    if (videoOutput)
     
    53115583
    53125584void NuppelVideoPlayer::UpdateSeekAmount(bool up)
    53135585{
    5314     if (seekamountpos > 0 && !up)
    5315         seekamountpos--;
    5316     if (seekamountpos < 9 && up)
    5317         seekamountpos++;
     5586    if (up)
     5587    {
     5588        if (seekamountpos < 11)
     5589            seekamountpos++;
     5590        if (allow_pagesize)
     5591        {
     5592            if (seekamountpos == 1)
     5593                seekamountpos = 2;
     5594        }
     5595        else
     5596        {
     5597            if (seekamountpos == 3 || seekamountpos == 4)
     5598                seekamountpos = 5;
     5599        }
     5600    }
     5601    else
     5602    {
     5603        if (seekamountpos > 0)
     5604            seekamountpos--;
     5605        if (allow_pagesize)
     5606        {
     5607            if (seekamountpos == 1)
     5608                seekamountpos =0;
     5609        }
     5610        else
     5611        {
     5612            if (seekamountpos == 3 || seekamountpos == 4)
     5613                seekamountpos = 2;
     5614        }
     5615    }
    53185616
    5319     QString text = "";
     5617    QString text;
    53205618
    53215619    switch (seekamountpos)
    53225620    {
    5323         case 0: text = QObject::tr("cut point"); seekamount = -2; break;
    5324         case 1: text = QObject::tr("keyframe"); seekamount = -1; break;
    5325         case 2: text = QObject::tr("1 frame"); seekamount = 1; break;
    5326         case 3: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break;
    5327         case 4: text = QObject::tr("1 second"); seekamount = (int)roundf(video_frame_rate); break;
    5328         case 5: text = QObject::tr("5 seconds"); seekamount = (int)roundf(video_frame_rate * 5); break;
    5329         case 6: text = QObject::tr("20 seconds"); seekamount = (int)roundf(video_frame_rate * 20); break;
    5330         case 7: text = QObject::tr("1 minute"); seekamount = (int)roundf(video_frame_rate * 60); break;
    5331         case 8: text = QObject::tr("5 minutes"); seekamount = (int)roundf(video_frame_rate * 300); break;
    5332         case 9: text = QObject::tr("10 minutes"); seekamount = (int)roundf(video_frame_rate * 600); break;
    5333         default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break;
     5621        case  0: text = QObject::tr("cut point");   seekamount = -2; break;
     5622
     5623        // Only for non-edit grid
     5624        case  1: text = QObject::tr("keyframe");    seekamount = -1; break;
     5625        // Only for non-edit grid
     5626
     5627        case  2: text = QObject::tr("1 frame");     seekamount =  1; break;
     5628
     5629        // Case 3 & 4 are for the edit grid only
     5630        case  3: text = QObject::tr("1/2 Page");    seekamount =  half_page; break;
     5631        case  4: text = QObject::tr("Full Page");   seekamount =  2*half_page; break;
     5632        // Case 3 & 4 are for the edit grid only
     5633
     5634        case  5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break;
     5635        case  6: text = QObject::tr("1 second");    seekamount = (int)roundf(video_frame_rate); break;
     5636        case  7: text = QObject::tr("5 seconds");   seekamount = (int)roundf(video_frame_rate * 5); break;
     5637        case  8: text = QObject::tr("20 seconds");  seekamount = (int)roundf(video_frame_rate * 20); break;
     5638        case  9: text = QObject::tr("1 minute");    seekamount = (int)roundf(video_frame_rate * 60); break;
     5639        case 10: text = QObject::tr("5 minutes");   seekamount = (int)roundf(video_frame_rate * 300); break;
     5640        case 11: text = QObject::tr("10 minutes");  seekamount = (int)roundf(video_frame_rate * 600); break;
     5641        default: text = QObject::tr("error");       seekamount = (int)roundf(video_frame_rate); break;
    53345642    }
    53355643
     5644    seekamounttext = text;
     5645    UpdateSeekAmountDisplay();
     5646}
     5647
     5648void NuppelVideoPlayer::UpdateSeekAmountDisplay(void)
     5649{
    53365650    QMap<QString, QString> infoMap;
    5337     infoMap["seekamount"] = text;
    5338     osd->SetText("editmode", infoMap, -1);
     5651    infoMap["seekamount"] = seekamounttext;
     5652    if (!hideedits)
     5653        osd->SetText("editmode", infoMap, -1);
    53395654}
    53405655
    53415656void NuppelVideoPlayer::UpdateTimeDisplay(void)
     
    53655680    infoMap["timedisplay"] = timestr;
    53665681    infoMap["framedisplay"] = framestr;
    53675682    infoMap["cutindicator"] = cutmarker;
    5368     osd->SetText("editmode", infoMap, -1);
     5683    if (!hideedits)
     5684        osd->SetText("editmode", infoMap, -1);
    53695685}
    53705686
    5371 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)
     5687DeletePointInfo NuppelVideoPlayer::GetDeletePointInfo(long long frame, bool allowSelectNear)
    53725688{
    5373     bool deletepoint = false;
    5374     bool cut_after = false;
    5375     int direction = 0;
     5689    DeletePointInfo retval;
    53765690
    53775691    if(!deleteMap.isEmpty())
    53785692    {
    53795693        QMap<long long, int>::ConstIterator iter = deleteMap.begin();
    53805694
    5381         while((iter != deleteMap.end()) && (iter.key() < framesPlayed))
     5695        while((iter != deleteMap.end()) && (iter.key() < frame))
    53825696            ++iter;
    53835697
    53845698        if (iter == deleteMap.end())
    53855699        {
    53865700            --iter;
    5387             cut_after = !iter.data();
     5701            retval.cut_after = !iter.data();
    53885702        }
    5389         else if((iter != deleteMap.begin()) && (iter.key() != framesPlayed))
     5703        else if((iter != deleteMap.begin()) && (iter.key() != frame))
    53905704        {
    53915705            long long value = iter.key();
    5392             if((framesPlayed - (--iter).key()) > (value - framesPlayed))
     5706            if((frame - (--iter).key()) > (value - frame))
    53935707            {
    5394                 cut_after = !iter.data();
     5708                retval.cut_after = !iter.data();
    53955709                ++iter;
    53965710            }
    53975711            else
    5398                 cut_after = !iter.data();
     5712                retval.cut_after = !iter.data();
    53995713        }
    54005714
    5401         direction = iter.data();
    5402         deleteframe = iter.key();
     5715        retval.direction = iter.data();
     5716        retval.deleteframe = iter.key();
    54035717
    5404         if ((absLongLong(deleteframe - framesPlayed) <
     5718        if ((absLongLong(retval.deleteframe - frame) <
    54055719                   (int)ceil(20 * video_frame_rate)) && !allowSelectNear)
    54065720        {
    5407             deletepoint = true;
     5721            retval.deletepoint = true;
    54085722        }
    54095723    }
     5724    return retval;
     5725}
    54105726
    5411     if (deletepoint)
     5727void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)
     5728{
     5729    DeletePointInfo dpi = GetDeletePointInfo(framesPlayed, allowSelectNear);
     5730    deleteframe = dpi.deleteframe;
     5731
     5732    if (dpi.deletepoint)
    54125733    {
    54135734        QString message = QObject::tr("You are close to an existing cut point. "
    54145735                                      "Would you like to:");
     
    54165737        QString option2 = QObject::tr("Move this cut point to the current "
    54175738                                      "position");
    54185739        QString option3 = QObject::tr("Flip directions - delete to the ");
    5419         if (direction == 0)
     5740        if (dpi.direction == 0)
    54205741            option3 += QObject::tr("right");
    54215742        else
    54225743            option3 += QObject::tr("left");
     
    54465767        options += option1;
    54475768        options += option2;
    54485769
    5449         osd->NewDialogBox(dialogname, message, options, -1, cut_after);
     5770        osd->NewDialogBox(dialogname, message, options, -1, dpi.cut_after);
    54505771    }
    54515772}
    54525773
     
    54975818
    54985819void NuppelVideoPlayer::UpdateEditSlider(void)
    54995820{
    5500     osd->DoEditSlider(deleteMap, framesPlayed, totalFrames);
     5821    if (!hideedits)
     5822        osd->DoEditSlider(deleteMap, framesPlayed, totalFrames);
    55015823}
    55025824
    55035825void NuppelVideoPlayer::AddMark(long long frames, int type)
    55045826{
    55055827    deleteMap[frames] = type;
    5506     osd->ShowEditArrow(frames, totalFrames, type);
     5828    if (!hideedits)
     5829        osd->ShowEditArrow(frames, totalFrames, type);
    55075830}
    55085831
    55095832void NuppelVideoPlayer::DeleteMark(long long frames)
    55105833{
    5511     osd->HideEditArrow(frames, deleteMap[frames]);
     5834    if (!hideedits)
     5835        osd->HideEditArrow(frames, deleteMap[frames]);
    55125836    deleteMap.remove(frames);
    55135837}
    55145838
    55155839void NuppelVideoPlayer::ReverseMark(long long frames)
    55165840{
    5517     osd->HideEditArrow(frames, deleteMap[frames]);
     5841    if (!hideedits)
     5842        osd->HideEditArrow(frames, deleteMap[frames]);
    55185843
    55195844    if (deleteMap[frames] == MARK_CUT_END)
    55205845        deleteMap[frames] = MARK_CUT_START;
    55215846    else
    55225847        deleteMap[frames] = MARK_CUT_END;
    55235848
    5524     osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]);
     5849    if (!hideedits)
     5850        osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]);
     5851}
     5852
     5853long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right)
     5854{
     5855    QMap<long long, int>::Iterator i = deleteMap.begin();                                     
     5856    long long framenum = -1;
     5857    long long seekcount = 0;
     5858    if (right)                                                                                 
     5859    {
     5860        for (; i != deleteMap.end(); ++i)                                                     
     5861        {
     5862            if (i.key() > baseframe)                                                       
     5863            {
     5864                framenum = i.key();                                                           
     5865                break;                                                                         
     5866            }                                                                                 
     5867        }                                                                                     
     5868        if (framenum == -1)
     5869            framenum = totalFrames;
     5870        seekcount = framenum - baseframe;
     5871    }
     5872    else
     5873    {
     5874        for (; i != deleteMap.end(); ++i)
     5875        {
     5876            if (i.key() >= baseframe)
     5877                break;
     5878            framenum = i.key();
     5879        }
     5880        if (framenum == -1)
     5881            framenum = 0;
     5882        seekcount = baseframe - framenum;
     5883    }
     5884    return seekcount;
    55255885}
    55265886
    55275887void NuppelVideoPlayer::HandleArbSeek(bool right)
    55285888{
    55295889    if (seekamount == -2)
    55305890    {
    5531         QMap<long long, int>::Iterator i = deleteMap.begin();
    5532         long long framenum = -1;
     5891        long long seekcount = CalcCutPointSeek(framesPlayed, right);
    55335892        if (right)
    55345893        {
    5535             for (; i != deleteMap.end(); ++i)
    5536             {
    5537                 if (i.key() > framesPlayed)
    5538                 {
    5539                     framenum = i.key();
    5540                     break;
    5541                 }
    5542             }
    5543             if (framenum == -1)
    5544                 framenum = totalFrames;
    5545 
    5546             fftime = framenum - framesPlayed;
     5894            fftime = seekcount;
    55475895            while (fftime > 0)
    55485896                usleep(1000);
    55495897        }
    55505898        else
    55515899        {
    5552             for (; i != deleteMap.end(); ++i)
    5553             {
    5554                 if (i.key() >= framesPlayed)
    5555                     break;
    5556                 framenum = i.key();
    5557             }
    5558             if (framenum == -1)
    5559                 framenum = 0;
    5560 
    5561             rewindtime = framesPlayed - framenum;
     5900            rewindtime = seekcount;
    55625901            while (rewindtime > 0)
    55635902                usleep(1000);
    55645903        }
     
    55895928    UpdateEditSlider();
    55905929}
    55915930
     5931int NuppelVideoPlayer::GetCutStatus(long long testframe) const
     5932{
     5933    int retval = 0;
     5934    QMap<long long, int>::const_iterator i;
     5935    i = deleteMap.find(testframe);
     5936    if (i == deleteMap.end()) {
     5937        // testframe is not an explicit cutpoint
     5938        // See if it is in a deleted area
     5939        if (IsInDelete(testframe))
     5940            retval = 1;
     5941    } else {
     5942        int direction = i.data();
     5943        if (direction == 0)
     5944            retval = 2;
     5945        else
     5946            retval = 3;
     5947    }
     5948
     5949    return retval;
     5950}
     5951
    55925952bool NuppelVideoPlayer::IsInDelete(long long testframe) const
    55935953{
    55945954    long long startpos = 0;
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/NuppelVideoPlayer.h release.20115.0305gridedit/mythtv/libs/libmythtv/NuppelVideoPlayer.h
     
    100100    kDisplayTeletextMenu        = 0x40,
    101101};
    102102
     103class DeletePointInfo
     104{
     105    public:
     106        DeletePointInfo() :
     107            deleteframe(0), deletepoint(false), cut_after(false), direction(0) {}
     108       
     109        long long deleteframe;
     110        bool deletepoint;
     111        bool cut_after;
     112        int direction;
     113};
     114
    103115class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
    104116{
     117 friend class GridEditCutpoints;
     118 friend class TV;
    105119 public:
    106120    NuppelVideoPlayer(QString inUseID = "Unknown",
    107121                      const ProgramInfo *info = NULL);
     
    270284    bool EnableEdit(void);
    271285    bool DoKeypress(QKeyEvent *e);
    272286    bool GetEditMode(void) const { return editmode; }
     287    bool GetHideEdits(void) const { return hideedits; }
    273288
    274289    // Decoder stuff..
    275290    VideoFrame *GetNextVideoFrame(bool allow_unsafe = true);
     
    289304    void ShutdownYUVResize(void);
    290305    void SaveScreenshot(void);
    291306
     307    // Edit stuff
     308    bool EditSeekToFrame(long long targetFrame);
     309    void SetScreenGrabSizes(QSize normal, QSize small);
     310    bool GetScreenGrabsOfCurrentFrame(QImage & normal, QImage &small); // Get current frame
     311
     312    void       EditHandleClearMap();
     313    void       EditHandleInvertMap();
     314    void       EditHandleLoadCommSkip();
     315
     316    void ShowEditRecordingGrid();
     317
    292318    // Reinit
    293319    void    ReinitOSD(void);
    294320    void    ReinitVideo(void);
     
    406432        hidedvdbutton = hide;
    407433    }
    408434
     435    // Stuf for GridEditCutpoints
     436    long long CalcCutPointSeek(long long baseframe, bool right);
     437    // returns
     438    // 0 - no cut
     439    // 1 - is deleted
     440    // 2 - cut left
     441    // 3 - cut right
     442    int  GetCutStatus(long long testframe) const;
     443    long long GetSeekAmount() { return seekamount; }
     444    QString GetSeekAmountText() { return seekamounttext; }
     445
    409446  protected:
    410447    void DisplayPauseFrame(void);
    411448    void DisplayNormalFrame(void);
     
    487524    void HandleSelect(bool allowSelectNear = false);
    488525    void HandleResponse(void);
    489526
     527    DeletePointInfo GetDeletePointInfo(long long frame, bool allowSelectNear);
     528    void SetupScreenGrab();
     529    void ClearScreenGrab();
     530
    490531    void UpdateTimeDisplay(void);
     532    int  GetSeekAmountPos() { return seekamountpos; }
    491533    void UpdateSeekAmount(bool up);
     534    void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; }
     535    void UpdateSeekAmountDisplay(void);
    492536    void UpdateEditSlider(void);
    493537
    494538    // Private A/V Sync Stuff
     
    560604    bool     livetv;
    561605    bool     watchingrecording;
    562606    bool     editmode;
     607    bool     hideedits;
    563608    bool     resetvideo;
    564609    bool     using_null_videoout;
    565610    bool     no_audio_in;
     
    579624    long long fftime;
    580625    /// 1..9 == keyframe..10 minutes. 0 == cut point
    581626    int       seekamountpos;
     627    ///  Used for Grid Edit logic
     628    bool      allow_pagesize;
     629    int       half_page;
    582630    /// Seekable frame increment when not using exact seeks.
    583631    /// Usually equal to keyframedist.
    584632    int      seekamount;
     633    QString  seekamounttext; // OSD seek units
    585634    /// Iff true we ignore seek amount and try to seek to an
    586635    /// exact frame ignoring key frame restrictions.
    587636    bool     exactseeks;
     
    714763    QMutex              yuv_lock;
    715764    QWaitCondition      yuv_wait;
    716765
     766    // EditGrid still image capture
     767    ImgReSampleContext *grid_edit_image_scaler;
     768    ImgReSampleContext *grid_edit_image_small_scaler;
     769    unsigned char      *grid_edit_image_buffer_yuv;
     770    unsigned char      *grid_edit_image_small_buffer_yuv;
     771    unsigned char      *grid_edit_image_buffer_rgb;
     772    unsigned char      *grid_edit_image_small_buffer_rgb;
     773    int                 grid_edit_image_buffer_length;
     774    int                 grid_edit_image_small_buffer_length;
     775    QSize               grid_edit_image_in_size;
     776    QSize               grid_edit_image_size;
     777    QSize               grid_edit_image_small_size;
     778
    717779    // Filters
    718780    QMutex   videofiltersLock;
    719781    QString  videoFiltersForProgram;
  • mythtv/libs/libmythtv/grideditcutpoints.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditcutpoints.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/grideditcutpoints.cpp
     
     1#include <qapplication.h>
     2#include <qpainter.h>
     3#include <qfont.h>
     4#include <qsqldatabase.h>
     5#include <qsqlquery.h>
     6#include <math.h>
     7#include <qcursor.h>
     8#include <qapplication.h>
     9#include <qimage.h>
     10#include <qlayout.h>
     11#include <qlabel.h>
     12#include <qdatetime.h>
     13#include <qvgroupbox.h>
     14#include <qheader.h>
     15#include <qrect.h>
     16
     17#include <unistd.h>
     18#include <iostream>
     19#include <algorithm>
     20using namespace std;
     21
     22#include "mythcontext.h"
     23#include "mythdbcon.h"
     24#include "grideditcutpoints.h"
     25#include "grideditimages.h"
     26#include "NuppelVideoPlayer.h"
     27
     28void GridEditCutpoints::Run(NuppelVideoPlayer *player)
     29{
     30    VERBOSE(VB_GENERAL, "Starting");
     31    gContext->addCurrentLocation("GridEditCutpoints");
     32
     33    GridEditCutpoints *er = new GridEditCutpoints(gContext->GetMainWindow(),
     34                                  player, "editrecording");
     35
     36    if (er->isValid())
     37    {
     38        er->Show();
     39        er->displayInitialFrame();
     40        er->exec();
     41    }
     42
     43    delete er;
     44
     45    gContext->removeCurrentLocation();
     46    VERBOSE(VB_GENERAL, "Ending");
     47}
     48
     49GridEditCutpoints::GridEditCutpoints(MythMainWindow *parent,
     50                     NuppelVideoPlayer *player, const char *name)
     51         : MythThemedDialog(parent, "grideditcutpoints", "", name)
     52{
     53    m_player = player;
     54    m_images = new GridEditImages(this, player);
     55
     56    int i;
     57    m_gridimagemain = NULL;
     58    for (i = m_gridimages.minIndex(); i < m_gridimages.maxIndex(); i++)
     59        m_gridimages[i] = NULL;
     60
     61    usedSubVideoCount=0;
     62
     63    QSize videoSizeMain, videoSizeSmall;
     64
     65    m_gridimagemain = getUIGridEditImageType("mainvideo");
     66    if (m_gridimagemain)
     67        videoSizeMain = m_gridimagemain->getScreenArea().size();
     68    else
     69    {
     70        VERBOSE(VB_IMPORTANT, "FATAL: Couldn't find mainedit:mainvideo");
     71        return;
     72    }
     73
     74    // Small version of main frame
     75    m_gridimages[0] = getUIGridEditImageType("video0");
     76
     77    for (i = 1; i < m_gridimages.maxIndex(); i++)
     78    {
     79        QString p = QString("videop%1").arg(i);
     80        QString m = QString("videom%1").arg(i);
     81
     82        // Minus frame i
     83        m_gridimages[-i] = getUIGridEditImageType(m);
     84        if (m_gridimages[-i])
     85        {
     86            QSize tmpVideoSizeSmall = m_gridimages[-i]->getScreenArea().size();
     87            if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall)
     88                VERBOSE(VB_IMPORTANT,
     89                        QString("Multiple sizes found for edit videos (%1)").arg(m));
     90            else
     91                videoSizeSmall = tmpVideoSizeSmall;
     92            if (i > usedSubVideoCount) usedSubVideoCount=i;
     93        }
     94
     95        m_gridimages[i] = getUIGridEditImageType(p);
     96        if (m_gridimages[i])
     97        {
     98            QSize tmpVideoSizeSmall = m_gridimages[i]->getScreenArea().size();
     99            if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall)
     100                VERBOSE(VB_IMPORTANT,
     101                        QString("Multiple sizes found for edit videos (%1)").arg(p));
     102            else
     103                videoSizeSmall = tmpVideoSizeSmall;
     104            if (i > usedSubVideoCount) usedSubVideoCount=i;
     105        }
     106    }
     107
     108    imageScreenArea = m_gridimages[-usedSubVideoCount]->getOuterBorder();
     109    for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++)
     110        if (m_gridimages[i])
     111            imageScreenArea = imageScreenArea.unite(m_gridimages[i]->getOuterBorder());
     112
     113    m_images->SetVideoInfo(usedSubVideoCount, videoSizeMain, videoSizeSmall);
     114
     115    m_player->SetHalfPageSize(usedSubVideoCount);
     116    m_slider = getUIGridEditSliderType("positionbar");
     117    if (!m_slider)
     118        VERBOSE(VB_GENERAL, "Missing positionbar for GridEditCutpoints");
     119
     120    // Get Status boxes
     121    {
     122        m_framenum    = getUITextType("framenum");
     123        m_time        = getUITextType("time");
     124        m_cutind      = getUITextType("cutind");
     125        m_jumpstyle   = getUITextType("jumpstyle");
     126        m_updatingind = getUITextType("updatingind");
     127    }
     128
     129    VERBOSE(VB_GENERAL, QString("main = (%1, %2) small = (%3, %4)")
     130                       .arg(videoSizeMain.width()).arg(videoSizeMain.height())
     131                       .arg(videoSizeSmall.width()).arg(videoSizeSmall.height()));
     132
     133    slowMotionDirection = 1; // start off play forward
     134    slowMotionActive = false;
     135    readyForNextFrame = false;
     136    slowMotionTimer = new QTimer(this);
     137    QObject::connect(slowMotionTimer, SIGNAL(timeout()),
     138                     this,           SLOT(updateSlowMotion()));
     139
     140    movingCutpoint = false;
     141    // Create blank pixmaps...
     142 
     143    updateBackground();
     144
     145    updateStats();
     146
     147    setNoErase();
     148    gContext->addListener(this);
     149   
     150    updateForeground();
     151}
     152
     153GridEditCutpoints::~GridEditCutpoints()
     154{
     155    if (m_images)
     156    {
     157        delete m_images;
     158        m_images = NULL;
     159    }
     160    gContext->removeListener(this);
     161}
     162
     163void GridEditCutpoints::displayInitialFrame()
     164{
     165    refreshImages();
     166    refreshCutList();
     167    updateStats();
     168    SetUpdating(false);
     169}
     170
     171void GridEditCutpoints::updateSlowMotion()
     172{
     173    if (!slowMotionActive)
     174        slowMotionTimer->stop();
     175    else if (readyForNextFrame && slowMotionDirection != 0)
     176    {
     177        readyForNextFrame=false;
     178
     179        if (slowMotionDirection > 0)
     180            EditHandleRight();
     181        else if (slowMotionDirection < 0)
     182            EditHandleLeft();
     183    }
     184}
     185
     186
     187void GridEditCutpoints::setSlowMotionSpeed()
     188{
     189    // slowMotionDirection is max FPS
     190
     191    if (slowMotionDirection != 0)
     192    {
     193        int smd = slowMotionDirection;
     194        if (smd < 0) smd = -smd;
     195        int timeout = 1000 / smd;
     196
     197        slowMotionTimer->start(timeout);
     198    }
     199    SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection));
     200}
     201
     202
     203void GridEditCutpoints::keyPressEvent(QKeyEvent *e)
     204{
     205    // keyDown limits keyrepeats to prevent continued scrolling
     206    // after key is released. Note: Qt's keycompress should handle
     207    // this but will fail with fast key strokes and keyboard repeat
     208    // enabled. Keys will not be marked as autorepeat and flood buffer.
     209    // setFocusPolicy(QWidget::ClickFocus) in constructor is important
     210    // or keyRelease events will not be received after a refocus.
     211   
     212    bool handled = false;
     213
     214    QStringList actions;
     215    gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions);
     216
     217    {
     218        for (unsigned int i = 0; i < actions.size() && !handled; i++)
     219        {
     220            QString action = actions[i];
     221            handled = true;
     222
     223            if (action == "SELECT")
     224            {
     225                if (slowMotionActive)
     226                {
     227                    slowMotionActive = false;
     228                    slowMotionTimer->stop();
     229                }
     230                else if (movingCutpoint)
     231                {
     232                    // Move cutpoint
     233                    m_player->DeleteMark(savedCutpoint);
     234                    m_player->AddMark(m_images->GetCurrentFrameNumber(), savedCutType);
     235                    movingCutpoint = false;
     236                    refreshCutList();
     237                    refreshImages();
     238                }
     239                else
     240                    handleSelect();
     241            }
     242            else if (action == "PAUSE")
     243            {
     244                if (movingCutpoint)
     245                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     246                                              "Moving Cutpoint",
     247                                              "Slow Motion Unavailable when moving cutpoint");
     248                else if (slowMotionActive)
     249                {
     250                    slowMotionActive = false;
     251                    slowMotionTimer->stop();
     252                }
     253            }
     254            else if (action == "SLOWMO")
     255            {
     256                if (movingCutpoint)
     257                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     258                                              "Moving Cutpoint",
     259                                              "Slow Motion Unavailable when moving cutpoint");
     260                else
     261                {
     262                    if (slowMotionActive)
     263                    {
     264                        slowMotionActive = false;
     265                        slowMotionTimer->stop();
     266                    }
     267                    else
     268                    {
     269                        slowMotionActive = true;
     270                        readyForNextFrame = true;
     271                        slowMotionDirection = 1;
     272
     273                        // force to either 1 frame. 1/2 page or full page motion
     274                        int i;
     275                        // move to 1 frame if on cutpoint
     276                        for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++)
     277                            m_player->UpdateSeekAmount(true);
     278
     279                        // move to fullpage if higher
     280                        for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++)
     281                            m_player->UpdateSeekAmount(false);
     282
     283                        setSlowMotionSpeed();
     284                    }
     285                }
     286            }
     287            else if (action == "LEFT")
     288            {
     289                if (slowMotionActive)
     290                {
     291                    slowMotionDirection--;
     292                    setSlowMotionSpeed();
     293                }
     294                else
     295                {
     296                    SetUpdating(true);
     297                    EditHandleLeft();
     298                }
     299            }
     300            else if (action == "RIGHT" )
     301            {
     302                if (slowMotionActive)
     303                {
     304                    slowMotionDirection++;
     305                    setSlowMotionSpeed();
     306                }
     307                else
     308                {
     309                    SetUpdating(true);
     310                    EditHandleRight();
     311                }
     312            }
     313            else if (action == "UP")
     314            {
     315                m_player->UpdateSeekAmount(true);
     316                updateStats();
     317            }
     318            else if (action == "DOWN")
     319            {
     320                if ((movingCutpoint || slowMotionActive) && m_player->GetSeekAmountPos() == 2)
     321                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     322                                              "Moving Cutpoint",
     323                                              "CutPoint skip Unavailable");
     324                else
     325                {
     326                    m_player->UpdateSeekAmount(false);
     327                    updateStats();
     328                }
     329            }
     330            else if (action == "CLEARMAP")
     331            {
     332                if (movingCutpoint || slowMotionActive)
     333                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     334                                              "Moving Cutpoint",
     335                                              "Clear Cut Map Unavailable");
     336                else
     337                {
     338                    SetUpdating(true);
     339                    m_player->EditHandleClearMap();
     340                    refreshCutList();
     341                    updateStats();
     342                }
     343            }
     344            else if (action == "INVERTMAP")
     345            {
     346                if (movingCutpoint || slowMotionActive)
     347                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     348                                              "Moving Cutpoint",
     349                                              "Invert Cut Map Unavailable");
     350                else
     351                {
     352                    SetUpdating(true);
     353                    m_player->EditHandleInvertMap();
     354                    refreshCutList();
     355                    updateStats();
     356                }
     357            }
     358            else if (action == "LOADCOMMSKIP")
     359            {
     360                if (movingCutpoint || slowMotionActive)
     361                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     362                                              "Moving Cutpoint",
     363                                              "Load Comm Skip Map Unavailable");
     364                else
     365                {
     366                    SetUpdating(true);
     367                    m_player->EditHandleLoadCommSkip();
     368                    refreshCutList();
     369                    updateStats();
     370                }
     371            }
     372            else if (action == "PREVCUT")
     373            {
     374                if (movingCutpoint || slowMotionActive)
     375                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     376                                              "Moving Cutpoint",
     377                                              "Prev Cut Unavailable");
     378                else
     379                {
     380                    SetUpdating(true);
     381                    EditHandlePrevCut();
     382                }
     383            }
     384            else if (action == "NEXTCUT")
     385            {
     386                if (movingCutpoint || slowMotionActive)
     387                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     388                                              "Moving Cutpoint",
     389                                              "Next Cut Unavailable");
     390                else
     391                {
     392                    SetUpdating(true);
     393                    EditHandleNextCut();
     394                }
     395            }
     396            else if (action == "BIGJUMPREW")
     397            {
     398                SetUpdating(true);
     399                EditHandleBigJumpRew();
     400            }
     401            else if (action == "BIGJUMPFWD")
     402            {
     403                SetUpdating(true);
     404                EditHandleBigJumpFwd();
     405            }
     406            else if (action == "ESCAPE" && movingCutpoint)
     407                movingCutpoint = false;
     408            else if (action == "ESCAPE" || action == "TOGGLEEDIT" ||
     409                     action == "MENU")
     410                escape();
     411            else
     412                handled = false;
     413
     414            if (movingCutpoint)
     415                SetUpdating(true, "Moving Cutpoint");
     416            else if (!slowMotionActive)
     417                SetUpdating(false);
     418        }
     419    }
     420
     421    if (!handled)
     422        MythDialog::keyPressEvent(e);
     423}
     424
     425void GridEditCutpoints::EditHandleLeft(int seektype)
     426{
     427    long long seekamount = m_player->GetSeekAmount();
     428    bool cutpointseek = false;
     429
     430    if (seektype == -2 || seekamount == -2)
     431        cutpointseek = true;
     432    else
     433    {
     434        // seektype == 1 for normal, 10 for bigjump
     435        seekamount *= seektype;
     436    }
     437
     438    if (seekamount < 0) // Invalid -- keyframe
     439        seekamount = 1;
     440
     441    m_images->SeekLeft(seekamount, cutpointseek);
     442
     443    refreshImages();
     444    updateStats();
     445}
     446
     447void GridEditCutpoints::EditHandleRight(int seektype)
     448{
     449    long long seekamount = m_player->GetSeekAmount();
     450    bool cutpointseek=false;
     451
     452    if (seektype == -2 || seekamount == -2)
     453        cutpointseek = true;
     454    else
     455    {
     456        // seektype == 1 for normal, 10 for bigjump
     457        seekamount *= seektype;
     458    }
     459
     460    if (seekamount < 0) // Invalid -- keyframe
     461        seekamount = 1;
     462
     463    m_images->SeekRight(seekamount, cutpointseek);
     464
     465    refreshImages();
     466    updateStats();
     467}
     468
     469void GridEditCutpoints::handleSelect(void)
     470{
     471    bool needupdate = false;
     472    // add / update cutpoint
     473    // -or-
     474    // delete / flip / move cutpoint
     475
     476    // if no cut points on screen
     477    //    "Delete Before"
     478    //    "Delete After"
     479
     480    // if on existing cutpoint
     481    //    "Delete cutpoint"
     482    //    "Flip directions"
     483
     484    // FIXME
     485    // if a cutpoint exists on the screen but not on the current frame
     486    //    "Move to current frame"
     487    //    "Add new"
     488
     489    FrameStats fs = m_images->GetMainFrameStats();
     490    DeletePointInfo dpi = m_player->GetDeletePointInfo(fs.frameNumber, true);
     491
     492    if (fs.cutInd >= 2)
     493    {
     494        QString title = "";
     495        QString message = "Cutpoint exists:";
     496        QStringList buttons;
     497        buttons.append("Delete cutpoint?");
     498        buttons.append("Move cutpoint?");
     499        if (fs.cutInd == 2)
     500            buttons.append("Flip directions (Cut After)?");
     501        else
     502            buttons.append("Flip directions (Cut Before)?");
     503
     504        DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
     505                                                      title, message, buttons, kDialogCodeButton0);
     506
     507
     508        if (dc != kDialogCodeRejected)
     509        {
     510            needupdate = true;
     511            if (dc == kDialogCodeButton0)
     512                // Delete cutpoint
     513                m_player->DeleteMark(fs.frameNumber);
     514
     515            else if (dc == kDialogCodeButton1)
     516            {
     517                // Move cutpoint
     518                savedCutpoint = fs.frameNumber;
     519                savedCutType = m_player->deleteMap[fs.frameNumber];
     520                movingCutpoint = true;
     521                // Ensure we're at least at 1 frame motion
     522                int i;
     523                for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++)
     524                    m_player->UpdateSeekAmount(true);
     525                   
     526            }
     527            else if (dc == kDialogCodeButton2)
     528                // Flip
     529                m_player->ReverseMark(fs.frameNumber);
     530        }
     531    }
     532    else
     533    {
     534        QString title = "";
     535        QString message = "Insert New Cutpoint?";
     536        QStringList buttons;
     537        buttons.append("Delete before this frame");
     538        buttons.append("Delete after this frame");
     539        DialogCode default_cut = (dpi.cut_after ? kDialogCodeButton1: kDialogCodeButton0);
     540        DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
     541                                                      title, message, buttons, default_cut);
     542
     543        if (dc != kDialogCodeRejected)
     544        {
     545            needupdate = true;
     546            if (dc == kDialogCodeButton0)
     547                // Delete left
     548                m_player->AddMark(fs.frameNumber, MARK_CUT_END);
     549
     550            else if (dc == kDialogCodeButton1)
     551                // Delete Right
     552                m_player->AddMark(fs.frameNumber, MARK_CUT_START);
     553        }
     554    }
     555
     556    if (needupdate)
     557    {
     558        refreshCutList();
     559        refreshImages();
     560    }
     561}
     562
     563void GridEditCutpoints::refreshImages()
     564{
     565    m_images->refreshImages(m_gridimagemain, m_gridimages, false);
     566    repaint(m_gridimagemain->getOuterBorder(), false);
     567    repaint(imageScreenArea, false);
     568}
     569
     570void GridEditCutpoints::refreshCutList()
     571{
     572    m_images->refreshCutList(m_gridimagemain, m_gridimages);
     573    refreshSlider();
     574}
     575
     576void GridEditCutpoints::refreshSlider()
     577{
     578    if (!m_slider)
     579        return;
     580
     581    m_slider->ClearAll();
     582
     583    const int CUT_LEFT = 0;
     584    const int CUT_RIGHT = 1;
     585
     586    long long startpos = 0;
     587    long long endpos = 0;
     588   
     589    int       lastdirection = CUT_LEFT;
     590
     591    QMap<long long, int> & deleteMap = m_player->deleteMap;
     592    QMap<long long, int>::Iterator i = deleteMap.begin();
     593    for (; i != deleteMap.end(); ++i)
     594    {
     595        long long frame = i.key();
     596        int direction = i.data();
     597
     598        if (direction == CUT_LEFT)
     599        {
     600            endpos = frame;
     601            m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber());
     602
     603            startpos = frame;
     604            lastdirection = CUT_LEFT;
     605        }
     606        else if (direction == CUT_RIGHT)
     607        {
     608            if (lastdirection == CUT_RIGHT)
     609            {
     610                // continuing within a cutpoint
     611                endpos = frame;
     612                m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber());
     613            }
     614
     615            startpos = frame;
     616            lastdirection = CUT_RIGHT;
     617        }
     618    }
     619
     620    if (lastdirection == CUT_RIGHT)
     621    {
     622        // continuing within a cutpoint
     623        endpos = m_images->GetMaxFrameNumber();
     624        m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber());
     625    }
     626}
     627
     628void GridEditCutpoints::updateStats(bool forcerepaint)
     629{
     630    int secs, frames, ss, mm, hh;
     631
     632    FrameStats fs = m_images->GetMainFrameStats();
     633
     634    secs = (int)(fs.frameNumber / m_player->GetFrameRate());
     635    frames = fs.frameNumber - (int)(secs * m_player->GetFrameRate());
     636
     637    ss = secs;
     638    mm = ss / 60;
     639    ss %= 60;
     640    hh = mm / 60;
     641    mm %= 60;
     642
     643    char timestr[128];
     644    sprintf(timestr, "%d:%02d:%02d.%02d", hh, mm, ss, frames);
     645
     646    char framestr[128];
     647    sprintf(framestr, "%lld", fs.frameNumber);
     648
     649    if (m_time)
     650    {
     651        m_time->SetText(timestr);
     652        if (forcerepaint)
     653            repaint(m_time->getScreenArea());
     654    }
     655    if (m_framenum)
     656    {
     657        m_framenum->SetText(framestr);
     658        if (forcerepaint)
     659            repaint(m_framenum->getScreenArea());
     660    }
     661    if (m_cutind)
     662    {
     663        switch (fs.cutInd) {
     664            case 0: m_cutind->SetText("");           break;
     665            case 1: m_cutind->SetText("Cut");        break;
     666            case 2: m_cutind->SetText("Cut Before"); break;
     667            case 3: m_cutind->SetText("Cut After");  break;
     668        }
     669        if (forcerepaint)
     670            repaint(m_cutind->getScreenArea());
     671    }
     672
     673    // Don't need to force update this
     674    if (m_jumpstyle)
     675        m_jumpstyle->SetText(m_player->GetSeekAmountText());
     676
     677    if (m_slider)
     678        m_slider->SetPosition(fs.frameNumber, fs.maxFrameNumber);
     679
     680}
     681
     682void GridEditCutpoints::escape()
     683{
     684    // Make sure we're on the right frame when we go back to
     685    // Normal edit mode
     686    unsetCursor();
     687    accept();
     688}
     689
     690void GridEditCutpoints::SetUpdating(bool active, QString text)
     691{
     692    if (m_updatingind)
     693    {
     694        //VERBOSE(VB_GENERAL, QString("Updating to %1").arg(active));
     695        if (active)
     696        {
     697            m_updatingind->show();
     698            m_updatingind->SetText(text);
     699        }
     700        else
     701            m_updatingind->hide();
     702        repaint(m_updatingind->getScreenArea());
     703    }
     704}
     705
     706void GridEditCutpoints::cacheFramesAreReady()
     707{
     708    if (slowMotionActive)
     709    {
     710        readyForNextFrame=true;
     711        if (!slowMotionTimer->isActive())
     712            slowMotionTimer->start(0);
     713    }
     714}
     715
  • mythtv/libs/libmythtv/grideditcutpoints.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditcutpoints.h release.20115.0305gridedit/mythtv/libs/libmythtv/grideditcutpoints.h
     
     1// -*- Mode: c++ -*-
     2#ifndef GRIDEDITCUTPOINTS_H_
     3#define GRIDEDITCUTPOINTS_H_
     4
     5#include <qstring.h>
     6
     7#include "libmyth/mythwidgets.h"
     8#include "uitypes.h"
     9
     10#include "grideditimages.h"
     11
     12using namespace std;
     13
     14class QTimer;
     15class NuppelVideoPlayer;
     16class GridEditImages;
     17
     18class MPUBLIC GridEditCutpoints : public MythThemedDialog
     19{
     20    Q_OBJECT
     21
     22  public:
     23    // Use this function to instantiate an GridEditCutpoints instance.
     24    static void Run(NuppelVideoPlayer            *player);
     25
     26    void refreshImages();
     27    void cacheFramesAreReady();
     28    bool isValid() { return ((usedSubVideoCount > 0) && (m_gridimagemain != NULL)); };
     29
     30  protected:
     31    GridEditCutpoints(MythMainWindow *parent,
     32              NuppelVideoPlayer *player, const char *name = "GridEditCutpoints");
     33   ~GridEditCutpoints();
     34
     35    void displayInitialFrame();
     36
     37    void handleSelect();
     38
     39    void updateStats(bool forcerepaint = false);
     40
     41  protected slots:
     42    void escape();
     43    void updateSlowMotion();
     44
     45  private:
     46    void keyPressEvent(QKeyEvent *e);
     47
     48    // seektype == -2 - cutpoint seek
     49    // seektype ==  1 - normal seek
     50    // seektype == 10 - large seek
     51    void EditHandleLeft(int seektype = 1);
     52    void EditHandleRight(int seektype = 1);
     53    void EditHandlePrevCut()    { EditHandleLeft(-2); };
     54    void EditHandleNextCut()    { EditHandleRight(-2); };
     55    void EditHandleBigJumpRew() { EditHandleLeft(10); };
     56    void EditHandleBigJumpFwd() { EditHandleRight(10); };
     57    void setSlowMotionSpeed();
     58    void refreshCutList();
     59    void refreshSlider();
     60
     61    void SetUpdating(bool active, QString text = "Updating");
     62
     63    // Private Data
     64
     65    NuppelVideoPlayer *m_player;
     66    GridEditImages *m_images;
     67
     68    int   usedSubVideoCount;
     69    myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> m_gridimages;
     70    // The main Big image
     71    UIGridEditImageType* m_gridimagemain;
     72
     73    long long savedCutpoint;
     74    int       savedCutType;
     75    bool      movingCutpoint;
     76
     77    UITextType   *m_framenum;
     78    UITextType   *m_time;
     79    UITextType   *m_cutind;
     80    UITextType   *m_jumpstyle;
     81    UITextType   *m_updatingind;
     82 
     83    UIGridEditSliderType  *m_slider;
     84    QTimer                *slowMotionTimer;
     85    int                    slowMotionDirection;
     86    bool                   slowMotionActive;
     87    bool                   readyForNextFrame;
     88
     89    QRect                  imageScreenArea;
     90};
     91
     92#endif
  • mythtv/libs/libmythtv/grideditimages.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditimages.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/grideditimages.cpp
     
     1#include <qapplication.h>
     2#include <qpainter.h>
     3#include <qfont.h>
     4#include <qsqldatabase.h>
     5#include <qsqlquery.h>
     6#include <math.h>
     7#include <qcursor.h>
     8#include <qapplication.h>
     9#include <qimage.h>
     10#include <qlayout.h>
     11#include <qlabel.h>
     12#include <qdatetime.h>
     13#include <qvgroupbox.h>
     14#include <qheader.h>
     15#include <qrect.h>
     16
     17#include <unistd.h>
     18#include <iostream>
     19#include <algorithm>
     20using namespace std;
     21
     22#include "mythcontext.h"
     23#include "mythdbcon.h"
     24#include "grideditimages.h"
     25#include "grideditcutpoints.h"
     26#include "NuppelVideoPlayer.h"
     27
     28#define FRAME_DEBUG 0
     29#define CACHE_DEBUG 1
     30
     31GridEditImages::GridEditImages(GridEditCutpoints *editor, NuppelVideoPlayer *player)
     32{
     33    m_editor = editor;
     34    m_player = player;
     35    usedSubVideoCount = 0;
     36
     37    lastmovewasright= true;
     38
     39    int i;
     40    for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++)
     41    {
     42        stillFrames[i] = NULL;
     43        stillFramesBig[i] = NULL;
     44        cutFrames[i] = 0;
     45    }
     46
     47    memset(cutFramesCache, 0, sizeof(cutFramesCache));
     48    memset(stillFramesCache, 0, sizeof(stillFramesCache));
     49    memset(stillFramesBigCache, 0, sizeof(stillFramesBigCache));
     50    stillFrameCacheCount = 0;
     51    stillFramesCacheBase = 0;
     52
     53
     54    // Get first frames...
     55    stillMainFrameNumber = m_player->GetFramesPlayed();
     56    if (stillMainFrameNumber <= 0)
     57        stillMainFrameNumber = 1;
     58
     59    // maxFrameNumber may be overridden if neccessary
     60    maxFrameNumber = m_player->GetTotalFrameCount();
     61    maxFrameNumberNVP = m_player->GetTotalFrameCount();
     62
     63    if (stillMainFrameNumber <= 0)
     64        stillMainFrameNumber = 1;
     65
     66    if (stillMainFrameNumber > maxFrameNumber)
     67        stillMainFrameNumber = maxFrameNumber;
     68
     69    getImagesTimer = new QTimer(this);
     70    QObject::connect(getImagesTimer, SIGNAL(timeout()),
     71                     this,           SLOT(updateAllFrames()));
     72
     73
     74}
     75
     76GridEditImages::~GridEditImages()
     77{
     78    emptyCache();
     79    clearStillFrames();
     80    m_player->EditSeekToFrame(stillMainFrameNumber);
     81}
     82
     83QPixmap *GridEditImages::makeScaledPixmap(const QImage& qim, QSize sz)
     84{
     85    QPixmap *retval;
     86    if (qim.size() == sz)
     87    {
     88        retval = new QPixmap(sz);
     89        QPainter p(retval);
     90        p.drawImage(0, 0, qim);
     91    }
     92    else
     93    {
     94        retval = new QPixmap(sz);
     95        retval->fill(Qt::black);
     96        QPainter p(retval);
     97
     98        int tl_left = 0;
     99        int tl_top = 0;
     100        if (sz.width() > qim.width())
     101            tl_left += (sz.width() - qim.width()) / 2;
     102
     103        if (sz.height() > qim.height())
     104            tl_top += (sz.height() - qim.height()) / 2;
     105
     106//        VERBOSE(VB_GENERAL, QString("Size mismatch qim(%1, %2) != sz(%3, %4) Shift to (%5, %6)")
     107//             .arg(qim.width()).arg(qim.height())
     108//             .arg(sz.width()).arg(sz.height())
     109//             .arg(tl_left).arg(tl_top));
     110
     111        p.drawImage(tl_left, tl_top, qim);
     112    }
     113    return retval;
     114}
     115
     116
     117void GridEditImages::getMainStillFrame()
     118{
     119    getSpecificFrame(0);
     120}
     121
     122bool GridEditImages::getFrameIndexes(int newlevel)
     123{
     124    // levels:
     125    // 0 - onscreen frames
     126    // 1 - precache frames
     127    // 2 - fill-out-the buffer frames
     128
     129    if (newlevel > 2)
     130        return false;
     131
     132    // This gets the upper and lower indexes of the frames we need to get.
     133    // Note these indexes maybe negative
     134    // Negative frames are before the main frame
     135    // Frame #0 is the main frame
     136    // Positive frames are after the main frame
     137
     138    // Basic initialization
     139    // Doesn't go to absolute end because it slows down seeking
     140    // when you go 1 frame left and right
     141    frameIndexLeft       = stillFrames.minIndex() + 4;
     142    frameIndexRight      = stillFrames.maxIndex() - 4;
     143    getFutureFramesFirst = false;
     144
     145    if (newlevel == 0) // Current Display only
     146    {
     147        frameIndexLeft  = -usedSubVideoCount;
     148        frameIndexRight =  usedSubVideoCount;
     149    }
     150    else
     151    {
     152        getFutureFramesFirst = lastmovewasright;
     153
     154        if (newlevel == 1) // PreCache only
     155        {
     156            // preCacheIndexLeft and Right are indexes for the frames to start and end on
     157            frameIndexLeft  = preCacheIndexLeft;
     158            frameIndexRight = preCacheIndexRight;
     159        }
     160    }
     161
     162    // Make sure we don't fall of the front of the file
     163    if (stillMainFrameNumber + frameIndexLeft <= 0)
     164        frameIndexLeft = -(stillMainFrameNumber-1);
     165
     166    // ... or the back of the file
     167    if (frameIndexRight > (maxFrameNumber - stillMainFrameNumber))
     168        frameIndexRight = (maxFrameNumber - stillMainFrameNumber);
     169
     170#if CACHE_DEBUG
     171    VERBOSE(VB_GENERAL, QString("Getting frames from %1 to %2 for level %3")
     172            .arg(frameIndexLeft).arg(frameIndexRight).arg(newlevel));
     173#endif
     174    return true;
     175}
     176
     177bool GridEditImages::getStillFrames(int maxcount)
     178{
     179    // returns true if no more frames to get
     180
     181    // This will fill in all the missing frames in the cache
     182
     183    long long i;
     184    if (getFutureFramesFirst && frameIndexLeft < 0)
     185    {
     186        // If we're filling out the cache and the last move was to the right
     187        // grab future frames first before any past frames
     188        for (i = 1; i <= frameIndexRight; i++)
     189            if (getSpecificFrame(i))
     190                if (--maxcount == 0) return false;
     191    }
     192
     193    // grab all appropriate frames
     194
     195    for (i = frameIndexLeft; i <= frameIndexRight; i++)
     196        if (getSpecificFrame(i))
     197            if (--maxcount == 0) return false;
     198
     199    return true;
     200}
     201
     202bool GridEditImages::getSpecificFrame(long long i)
     203{
     204    // i is the index within the cache of frames
     205
     206    // If we're outside of the normal boundaries of the buffer,
     207    // see if we've precached this frame
     208    if (i < stillFrames.minIndex() || i > stillFrames.maxIndex())
     209    {
     210        // First extra cached frame
     211        if (stillFrameCacheCount == 0)
     212            stillFramesCacheBase = stillMainFrameNumber + i;
     213
     214        int tmpi;
     215        for (tmpi = 0; tmpi < stillFrameCacheCount; tmpi++)
     216        {
     217            long long tmpframe = (stillFramesCacheBase + tmpi);
     218            if (tmpframe == stillMainFrameNumber + i)
     219                return false;
     220        }
     221
     222        // Check for cache overflow
     223        if (stillFrameCacheCount >= MAX_SUB_VIDEOS)
     224        {
     225            VERBOSE(VB_GENERAL, QString("Cached too many videos. Max = %1").arg(MAX_SUB_VIDEOS));
     226            return false;
     227        }
     228       
     229        tmpi = stillFrameCacheCount++;
     230
     231#if CACHE_DEBUG
     232        VERBOSE(VB_GENERAL, QString("Caching frame %1, (frm# %2, index %3)")
     233                            .arg(tmpi).arg(stillMainFrameNumber + i)
     234                            .arg(i));
     235#endif
     236
     237        getFrame(i, cutFramesCache[tmpi], stillFramesCache[tmpi], stillFramesBigCache[tmpi]);
     238        return true;
     239    }
     240    else if (!stillFrames[i])
     241    {
     242        getFrame(i, cutFrames[i], stillFrames[i], stillFramesBig[i]);
     243        return true;
     244    }
     245
     246    return false;
     247}
     248
     249void GridEditImages::getFrame(long long i,
     250        int &cutFrame,
     251        QPixmap * &stillFrame,
     252        QPixmap * &stillFrameBig)
     253{
     254    // get this frame
     255    long long targetFrame = stillMainFrameNumber + i;
     256
     257    if (!m_player->EditSeekToFrame(targetFrame))
     258    {
     259        VERBOSE(VB_GENERAL, QString("Error seeking to Frame[%1] (frame # %2)")
     260                            .arg(i).arg(targetFrame));
     261        checkMaxFrameCount();
     262
     263        stillFrameBig = new QPixmap(videoSizeMain);
     264        stillFrameBig->fill(Qt::gray);
     265
     266        stillFrame = new QPixmap(videoSizeSmall);
     267        stillFrame->fill(Qt::gray);
     268    }
     269    else
     270    {
     271        cutFrame = m_player->GetCutStatus(targetFrame);
     272        QImage normal, small;
     273        m_player->GetScreenGrabsOfCurrentFrame(normal, small);
     274
     275        stillFrameBig = makeScaledPixmap(normal, videoSizeMain);
     276        stillFrame    = makeScaledPixmap(small, videoSizeSmall);
     277
     278#if FRAME_DEBUG
     279        VERBOSE(VB_GENERAL, QString("stillFrames[%1] = %2 (%3)")
     280                .arg(i)
     281                .arg(targetFrame)
     282                .arg(cutFrame));
     283#endif
     284    }
     285}
     286
     287void GridEditImages::SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall)
     288{
     289    usedSubVideoCount = vcount;
     290    videoSizeMain = sizeMain;
     291    videoSizeSmall = sizeSmall;
     292    SetPreCache(1);
     293
     294    m_player->SetScreenGrabSizes(videoSizeMain, videoSizeSmall);
     295
     296    // start to grab the current images
     297    getMainStillFrame();
     298    startFrameCaching();
     299}
     300
     301void GridEditImages::startFrameCaching()
     302{
     303    frameCacheLevel=0;
     304    getFrameIndexes(frameCacheLevel);
     305   
     306    getImagesTimer->start(0);
     307}
     308
     309void GridEditImages::SetPreCache(long long pccount)
     310{
     311    preCacheIndexLeft  = pccount - usedSubVideoCount;
     312    preCacheIndexRight = pccount + usedSubVideoCount;
     313}
     314
     315void GridEditImages::updateAllFrames()
     316{
     317    // getStillFrames() returns 'true' on the next call after it's gotten all requested frames
     318
     319    if (getStillFrames(1))
     320    {
     321        // If we've pre-cached the next screen of frames, tell the editor about it
     322        if (frameCacheLevel == 1)
     323            m_editor->cacheFramesAreReady();
     324
     325        frameCacheLevel++;
     326        if (getFrameIndexes(frameCacheLevel))
     327            getStillFrames(1);
     328        else
     329            stopFrameCaching();
     330    }
     331    m_editor->refreshImages();
     332}
     333
     334void GridEditImages::clearStillFrames()
     335{
     336    int i;
     337    for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++)
     338    {
     339        if (stillFrames[i])
     340        {
     341            delete stillFrames[i];
     342            stillFrames[i] = NULL;
     343        }
     344        if (stillFramesBig[i])
     345        {
     346            delete stillFramesBig[i];
     347            stillFramesBig[i] = NULL;
     348        }
     349        cutFrames[i] = 0;
     350    }
     351}
     352
     353bool GridEditImages::shiftStillFramesLeft(long long offset)
     354{
     355    if (offset > 2 * stillFrames.maxIndex())
     356    {
     357        // Dump all cached data and re-get it
     358        clearStillFrames();
     359    }
     360    else if (offset < 0)
     361    {
     362        VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset));
     363        // Dump all cached data and re-get it
     364        clearStillFrames();
     365        offset = 0;
     366    }
     367    else if (offset != 0)
     368    {
     369        // Shift backwards in the stream by offset
     370
     371        // All frames will actually shift to the right.
     372        // frame 'n' will become frame 'n+1'
     373        // frame stillFrameMinus[1] will become mainframe
     374        // frame stillFramePlus[max] will drop off
     375
     376        // shove extra frames into the excess space above usedSubVideos
     377
     378        if (offset >= stillMainFrameNumber)
     379            offset = (stillMainFrameNumber-1);
     380
     381        //    printStillFrameStats("Before SL");
     382        int i,j;
     383        int minIndex = stillFrames.minIndex();
     384        int maxIndex = stillFrames.maxIndex();
     385        for (i = 0; i < offset; i++)
     386        {
     387           
     388            if (stillFrames[maxIndex])
     389            {
     390                delete stillFrames[maxIndex];
     391                delete stillFramesBig[maxIndex];
     392            }
     393
     394            for (j = maxIndex; j > minIndex; j--) {
     395                stillFrames[j]    = stillFrames[j-1];
     396                stillFramesBig[j] = stillFramesBig[j-1];
     397                cutFrames[j]      = cutFrames[j-1];
     398            }
     399
     400             stillFrames[minIndex]    = NULL;
     401             stillFramesBig[minIndex] = NULL;
     402             cutFrames[minIndex]      = 0;
     403        }
     404
     405        //   printStillFrameStats("After SL");
     406
     407    }
     408
     409    stillMainFrameNumber -= offset;
     410    if (stillMainFrameNumber < 1)
     411        stillMainFrameNumber = 1;
     412
     413    emptyCache();
     414
     415    return (stillFramesBig[0] != NULL);
     416}
     417
     418bool GridEditImages::shiftStillFramesRight(long long offset)
     419{
     420    //VERBOSE(VB_GENERAL, QString("Offset =  %1").arg(offset));
     421    if (offset > 2 * stillFrames.maxIndex())
     422    {
     423        // Dump all cached data and re-get it
     424        clearStillFrames();
     425    }
     426    else if (offset < 0)
     427    {
     428        VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset));
     429        // Dump all cached data and re-get it
     430        clearStillFrames();
     431        offset = 0;
     432    }
     433    else if (offset != 0)
     434    {
     435
     436        // Shift forwards in the stream by offset
     437
     438        // All frames will actually shift to the left.
     439        // frame 'n' will become frame 'n-1'
     440        // frame stillFramePlus[1] will become mainframe
     441        // frame stillFrameMinus[max] will drop off
     442
     443        // shove extra frames into the excess space above usedSubVideos
     444
     445        if (stillMainFrameNumber + offset > maxFrameNumber)
     446        {
     447            offset = (maxFrameNumber - stillMainFrameNumber);
     448            VERBOSE(VB_GENERAL, QString("new Offset =  %1").arg(offset));
     449        }
     450        //printStillFrameStats("Before SR");
     451
     452        int i,j;
     453        int minIndex = stillFrames.minIndex();
     454        int maxIndex = stillFrames.maxIndex();
     455
     456        for (i = 0; i < offset; i++)
     457        {
     458            if (stillFrames[minIndex])
     459            {
     460                delete stillFrames[minIndex];
     461                delete stillFramesBig[minIndex];
     462            }
     463
     464            for (j = minIndex; j < maxIndex; j++) {
     465                stillFrames[j]    = stillFrames[j+1];
     466                stillFramesBig[j] = stillFramesBig[j+1];
     467                cutFrames[j]      = cutFrames[j+1];
     468            }
     469
     470             stillFrames[maxIndex]    = NULL;
     471             stillFramesBig[maxIndex] = NULL;
     472             cutFrames[maxIndex]      = 0;
     473        }
     474
     475        //printStillFrameStats("After SR");
     476
     477    }
     478    stillMainFrameNumber += offset;
     479    if (stillMainFrameNumber > maxFrameNumber )
     480        stillMainFrameNumber = maxFrameNumber;
     481
     482    emptyCache();
     483
     484    return (stillFramesBig[0] != NULL);
     485}
     486
     487void GridEditImages::emptyCache()
     488{
     489#if CACHE_DEBUG
     490    if (stillFrameCacheCount > 0)
     491    {
     492        long long minindex = (stillFramesCacheBase - stillMainFrameNumber);
     493        long long maxindex = (stillFramesCacheBase+stillFrameCacheCount-1) - stillMainFrameNumber;
     494        VERBOSE(VB_GENERAL, QString("emptying %1 frames (%2 - %3) into [%4] - [%5] ")
     495                            .arg(stillFrameCacheCount)
     496                            .arg(stillFramesCacheBase)
     497                            .arg(stillFramesCacheBase+(stillFrameCacheCount-1))
     498                            .arg(minindex).arg(maxindex));
     499    }
     500#endif
     501    int i;
     502    for (i = 0; i < stillFrameCacheCount; i++)
     503    {
     504        long long tmpframe = stillFramesCacheBase + i;
     505        long long frameIndex = tmpframe - stillMainFrameNumber;
     506
     507        // frameIndex is the index matching stillFramesCache[i] to stillFrames[frameIndex]
     508        // If frameIndex is within the stillFrames range, then use this frame
     509        // otherwise delete it
     510
     511        if (frameIndex >= stillFrames.minIndex() && frameIndex <= stillFrames.maxIndex())
     512        {
     513            // move cache data into normal arrays.
     514            if (stillFrames[frameIndex])
     515            {
     516                VERBOSE(VB_GENERAL, QString("Frame %1 index %2 already exists")
     517                                    .arg(tmpframe).arg(frameIndex));
     518                // Can't move it -- the destination exists
     519                delete stillFramesCache[i];
     520                delete stillFramesBigCache[i];
     521            }
     522            else
     523            {
     524                cutFrames[frameIndex] = cutFramesCache[i];
     525                stillFrames[frameIndex] = stillFramesCache[i];
     526                stillFramesBig[frameIndex] = stillFramesBigCache[i];
     527            }
     528        }
     529        else
     530        {
     531            delete stillFramesCache[i];
     532            delete stillFramesBigCache[i];
     533        }
     534        cutFramesCache[i]=0;
     535        stillFramesCache[i] = NULL;
     536        stillFramesBigCache[i] = NULL;
     537    }
     538    stillFrameCacheCount = 0;
     539}
     540
     541void GridEditImages::printStillFrameStats(QString caption)
     542{
     543    int i;
     544    // Debug info for frame cache
     545    QString foundframes= caption + " Found Frames: ";
     546
     547    for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++)
     548        if (stillFrames[i])
     549            foundframes += QString("%1 ").arg(i);
     550
     551    VERBOSE(VB_GENERAL, foundframes);
     552}
     553
     554void GridEditImages::refreshCutList(UIGridEditImageType* gridimagemain,
     555                                    myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages)
     556{
     557    int i;
     558
     559    for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++)
     560    {
     561        if (stillFrames[i])
     562        {
     563            cutFrames[i] = m_player->GetCutStatus(stillMainFrameNumber+i);
     564            if (gridimages[i])
     565                gridimages[i]->setCutStatus(cutFrames[i]);
     566        }
     567    }
     568    gridimagemain->setCutStatus(cutFrames[0]);
     569}
     570
     571bool GridEditImages::refreshImages(UIGridEditImageType* gridimagemain,
     572                                   myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages,
     573                                   bool mainFrameOnly)
     574{
     575//    VERBOSE(VB_GENERAL, "Start");
     576    bool alldone = true;
     577    if (!stillFramesBig[0])
     578        VERBOSE(VB_GENERAL, QString("Null Big Main frame %1").arg(stillMainFrameNumber));
     579    gridimagemain->setPixmap(stillFramesBig[0],
     580                             stillMainFrameNumber,
     581                             cutFrames[0]);
     582
     583    if (mainFrameOnly && gridimages[0])
     584        gridimages[0]->setPixmap(stillFrames[0],
     585                                 stillMainFrameNumber,
     586                                 cutFrames[0]);
     587
     588    if (!mainFrameOnly)
     589    {
     590        int i;
     591        for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++)
     592        {
     593            if (stillFrames[i] == NULL)
     594                alldone = false;
     595            if (gridimages[i])
     596                gridimages[i]->setPixmap(stillFrames[i],
     597                                         (stillMainFrameNumber + i),
     598                                         cutFrames[i]);
     599        }
     600    }
     601
     602//    VERBOSE(VB_GENERAL, "Finish");
     603    return alldone;
     604}
     605
     606
     607// Back up x frames
     608void GridEditImages::SeekLeft(long long seekamount, bool cutpointseek)
     609{
     610    lastmovewasright = false;
     611    stopFrameCaching();
     612
     613    if (cutpointseek)
     614        seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, false);
     615   
     616    //VERBOSE(VB_GENERAL, QString("SeekLeft %1, cutpoint = %2").arg(seekamount).arg(cutpointseek));
     617
     618    if (cutpointseek)
     619        SetPreCache(-1);
     620    else
     621        SetPreCache(-seekamount);
     622
     623    if (!shiftStillFramesLeft(seekamount))
     624    {
     625        //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false")
     626        //                           .arg(seekamount));
     627        // Need to grab the main frame
     628
     629        getMainStillFrame();
     630    }
     631
     632    startFrameCaching();
     633}
     634
     635void GridEditImages::SeekRight(long long seekamount, bool cutpointseek)
     636{
     637    lastmovewasright = true;
     638    stopFrameCaching();
     639
     640    if (cutpointseek)
     641        seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, true);
     642
     643    //VERBOSE(VB_GENERAL, QString("SeekRight %1, cutpoint = %2").arg(seekamount).arg(cutpointseek));
     644
     645    if (cutpointseek)
     646        SetPreCache(1);
     647    else
     648        SetPreCache(seekamount);
     649
     650    if (!shiftStillFramesRight(seekamount))
     651    {
     652        //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false")
     653        //                           .arg(seekamount));
     654        // Need to grab the main frame
     655
     656        getMainStillFrame();
     657    }
     658
     659    startFrameCaching();
     660}
     661
     662void GridEditImages::checkMaxFrameCount()
     663{
     664    long long tfc = m_player->GetTotalFrameCount();
     665    if (tfc != maxFrameNumberNVP)
     666    {
     667       VERBOSE(VB_GENERAL, QString("Updating: tfc %1, mfn %2, mfnNVP %3")
     668            .arg(tfc).arg(maxFrameNumber).arg(maxFrameNumberNVP));
     669        // Check to see if things changed
     670        maxFrameNumber = tfc;
     671        maxFrameNumberNVP = tfc;
     672    }
     673}
     674
     675FrameStats GridEditImages::GetMainFrameStats()
     676{
     677    FrameStats result;
     678
     679    result.frameNumber = stillMainFrameNumber;
     680    result.cutInd  = cutFrames[0];
     681    result.maxFrameNumber = maxFrameNumber;
     682
     683    return result;
     684}
     685
  • mythtv/libs/libmythtv/grideditimages.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditimages.h release.20115.0305gridedit/mythtv/libs/libmythtv/grideditimages.h
     
     1// -*- Mode: c++ -*-
     2#ifndef GRIDEDITIMAGES_H_
     3#define GRIDEDITIMAGES_H_
     4
     5#include <qstring.h>
     6
     7#include "libmyth/mythwidgets.h"
     8
     9using namespace std;
     10
     11class QTimer;
     12class NuppelVideoPlayer;
     13class GridEditCutpoints;
     14
     15#define MAX_SUB_VIDEOS 25
     16
     17// Simple class to allow array indexing from -MAX_SUB_VIDEOS to +MAX_SUB_VIDEOS
     18template<class T, int COUNT> class myArray
     19{
     20    public:
     21        myArray() { memset(_array, 0, sizeof(_array));};
     22
     23        T& operator[](int i) { return _array[COUNT+i]; };
     24        int minIndex() const { return -COUNT; };
     25        int maxIndex() const { return  COUNT; };
     26
     27    private:
     28        T _array[2*COUNT+1];
     29};
     30
     31class FrameStats
     32{
     33    public:
     34        long long frameNumber;
     35        int cutInd;
     36        long long maxFrameNumber;
     37};
     38
     39class MPUBLIC GridEditImages : public QObject
     40{
     41    Q_OBJECT
     42
     43    public:
     44        GridEditImages(GridEditCutpoints *er, NuppelVideoPlayer *player);
     45        ~GridEditImages();
     46
     47        void refreshCutList(UIGridEditImageType* gridimagemain, myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages);
     48
     49        // return true if anything changed
     50        bool refreshImages(UIGridEditImageType* gridimagemain,
     51                           myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages,
     52                           bool mainFrameOnly);
     53
     54        void SeekLeft(long long seekamount, bool cutpointseek = false);
     55        void SeekRight(long long seekamount, bool cutpointseek = false);
     56
     57        FrameStats GetMainFrameStats();
     58        long long GetCurrentFrameNumber() const { return stillMainFrameNumber; }
     59        long long GetMaxFrameNumber() const { return maxFrameNumber; }
     60
     61        void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall);
     62
     63    protected slots:
     64        void updateAllFrames();
     65
     66    private:
     67        // Private functions
     68        void clearStillFrames();
     69        void printStillFrameStats(QString caption);
     70        void checkMaxFrameCount();
     71
     72        // 'newlevel' paramter for getFrameIndexes():
     73        //  0 = get on screen Frames only
     74        //  1 = get preCache Frames only
     75        //  2 = get any necessary frames
     76        //  3 = done
     77        bool getFrameIndexes(int newlevel);
     78
     79        bool getStillFrames(int maxcount = 1000);
     80        void getMainStillFrame();
     81        bool getSpecificFrame(long long frameindex);
     82        void getFrame(long long i, int &cutFrame, QPixmap* &stillFrame, QPixmap* &stillFrameBig);
     83        void emptyCache();
     84
     85        // return true if anything changed
     86        bool shiftStillFramesLeft(long long offset);
     87        bool shiftStillFramesRight(long long offset);
     88        void startFrameCaching();
     89        void stopFrameCaching() { getImagesTimer->stop(); };
     90
     91        QPixmap *makeScaledPixmap(const QImage& qim, QSize sz);
     92
     93        void SetPreCache(long long pccount);
     94
     95        // Private data
     96        // These frames are in the cutlist
     97        // 0 == not cut
     98        // 1 == cut
     99        // 2 == cutpoint (cut left)
     100        // 3 == cutpoint (cut right)
     101        myArray<int, MAX_SUB_VIDEOS> cutFrames;
     102        myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames;
     103        myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig;
     104
     105        // Right and Left are for pre-caching large seek amounts
     106        // (i.e. while seeking +5 seconds, they're places to store the previously displayed data)
     107        // If there is any overlap, the main arrays hold the pointers
     108
     109        int       cutFramesCache[MAX_SUB_VIDEOS];
     110        QPixmap  *stillFramesCache[MAX_SUB_VIDEOS];
     111        QPixmap  *stillFramesBigCache[MAX_SUB_VIDEOS];
     112        int       stillFrameCacheCount;
     113        long long stillFramesCacheBase; // Frame # for index[0]
     114
     115        QSize     videoSizeMain;
     116        QSize     videoSizeSmall;
     117        int       usedSubVideoCount;
     118        long long preCacheIndexLeft;
     119        long long preCacheIndexRight;
     120        long long frameIndexLeft;
     121        long long frameIndexRight;
     122        bool      lastmovewasright;
     123        bool      getFutureFramesFirst;
     124        int       frameCacheLevel;
     125
     126        long long stillMainFrameNumber; // frame number for big still picture
     127        long long currentFrameNumberNVP; // frame number the NVP should be on
     128        long long maxFrameNumber;       // max frame number override for NVP
     129        long long maxFrameNumberNVP;    // Original NVP number
     130
     131        GridEditCutpoints *m_editor;
     132        NuppelVideoPlayer *m_player;
     133
     134        QTimer            *getImagesTimer;
     135
     136};
     137
     138#endif
  • mythtv/libs/libmythtv/libmythtv.pro

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/libmythtv.pro release.20115.0305gridedit/mythtv/libs/libmythtv/libmythtv.pro
     
    319319    # Misc. frontend
    320320    HEADERS += guidegrid.h              infostructs.h
    321321    HEADERS += progfind.h               ttfont.h
     322    HEADERS += grideditcutpoints.h      grideditimages.h
    322323    SOURCES += guidegrid.cpp            infostructs.cpp
    323324    SOURCES += progfind.cpp             ttfont.cpp
     325    SOURCES += grideditcutpoints.cpp    grideditimages.cpp
    324326
    325327    # DSMCC stuff
    326328    HEADERS += dsmcc.h                  dsmcccache.h
  • mythtv/libs/libmythtv/tv_play.cpp

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/tv_play.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/tv_play.cpp
     
    2525#include "remoteencoder.h"
    2626#include "remoteutil.h"
    2727#include "guidegrid.h"
     28#include "grideditcutpoints.h"
    2829#include "progfind.h"
    2930#include "NuppelVideoPlayer.h"
    3031#include "programinfo.h"
     
    440441    REG_KEY("TV Editing", "BIGJUMPFWD", "Jump forward 10x the normal amount",
    441442            ">,.");
    442443    REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E");
     444    REG_KEY("TV Editing", "SLOWMO", "Slow Motion Play", "Ctrl+P");
     445    REG_KEY("TV Editing", "PAUSE", "Pause", "P");
    443446
    444447    /* Teletext keys */
    445448    REG_KEY("Teletext Menu", "NEXTPAGE",    "Next Page",             "Down");
     
    26062609
    26072610    if (editmode)
    26082611    {   
     2612        if (nvp->GetHideEdits())
     2613            return;   
    26092614        if (!nvp->DoKeypress(e))
    26102615            editmode = nvp->GetEditMode();
    26112616        if (!editmode)
     
    59925997    qApp->postEvent(myWindow, me);
    59935998}
    59945999
     6000void TV::ShowEditRecordingGrid()
     6001{
     6002    // post the request to the main UI thread
     6003    // it will be caught in eventFilter and processed as CustomEvent
     6004    // this will create the program guide window (widget)
     6005    // on the main thread and avoid a deadlock on Win32
     6006
     6007    VERBOSE(VB_GENERAL, "Starting Grid Edit");
     6008    QString message = QString("START_EDIT");
     6009    MythEvent* me = new MythEvent(message);
     6010    qApp->postEvent(myWindow, me);
     6011}
     6012
    59956013void TV::ChangeVolume(bool up)
    59966014{
    59976015    AudioOutput *aud = nvp->getAudioOutput();
     
    65256543            int editType = tokens[1].toInt();
    65266544            doEditSchedule(editType);
    65276545        }
     6546        else if (message.left(10) == "START_EDIT")
     6547        {
     6548            nvp->ShowEditRecordingGrid();
     6549        }
    65286550
    65296551        pbinfoLock.lock();
    65306552        if (playbackinfo && message.left(14) == "COMMFLAG_START")
  • mythtv/libs/libmythtv/tv_play.h

    diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/tv_play.h release.20115.0305gridedit/mythtv/libs/libmythtv/tv_play.h
     
    158158    void setUnderNetworkControl(bool setting) { underNetworkControl = setting; }
    159159    bool IsSameProgram(ProgramInfo *p);
    160160
     161    void ShowEditRecordingGrid();
    161162    void ShowNoRecorderDialog(void);
    162163    void FinishRecording(void);
    163164    void AskAllowRecording(const QStringList&, int, bool, bool);