Ticket #6322: gridedit.trunk.code.5.patch

File gridedit.trunk.code.5.patch, 104.3 KB (added by anonymous, 15 years ago)
  • mythtv/libs/libmyth/mythdialogs.cpp

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/mythdialogs.cpp myth.20155.0309b/mythtv/libs/libmyth/mythdialogs.cpp
     
    13271327        rect_to_update = this->geometry();
    13281328    }
    13291329
    1330     redrawRect = redrawRect.unite(r);
     1330    redrawRect = redrawRect.unite(rect_to_update);
    13311331
    13321332    update(redrawRect);
    13331333}
     
    16521652    return GetUIType<UIBlackHoleType>(this, name);
    16531653}
    16541654
     1655UIGridEditImageType* MythThemedDialog::getUIGridEditImageType(const QString &name)
     1656{
     1657    return GetUIType<UIGridEditImageType>(this, name);
     1658}
     1659
     1660UIGridEditSliderType* MythThemedDialog::getUIGridEditSliderType(const QString &name)
     1661{
     1662    return GetUIType<UIGridEditSliderType>(this, name);
     1663}
     1664
    16551665UIImageType* MythThemedDialog::getUIImageType(const QString &name)
    16561666{
    16571667    return GetUIType<UIImageType>(this, name);
  • mythtv/libs/libmyth/mythdialogs.h

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/mythdialogs.h myth.20155.0309b/mythtv/libs/libmyth/mythdialogs.h
     
    2626class UICheckBoxType;
    2727class UISelectorType;
    2828class UIBlackHoleType;
     29class UIGridEditImageType;
     30class UIGridEditSliderType;
    2931class UIImageType;
    3032class UIImageGridType;
    3133class 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 myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/uitypes.cpp myth.20155.0309b/mythtv/libs/libmyth/uitypes.cpp
     
    46834683
    46844684// ********************************************************************
    46854685
     4686UIGridEditImageType::UIGridEditImageType(const QString &name)
     4687                     : UIType(name)
     4688{
     4689    cutStatus = 0;
     4690    highlightFrame = false; // Used to highlight frame #0
     4691    framenumber = -1;
     4692}
     4693
     4694void UIGridEditImageType::calculateScreenArea()
     4695{
     4696    QRect r = area;
     4697    r.translate(m_parent->GetAreaRect().left(),
     4698                m_parent->GetAreaRect().top());
     4699    screen_area = r;
     4700
     4701    inner_border.setLeft(screen_area.left()+1);
     4702    inner_border.setRight(screen_area.right()-1);
     4703    inner_border.setTop(screen_area.top()+1);
     4704    inner_border.setBottom(screen_area.bottom()-1);
     4705
     4706    outer_border = screen_area;
     4707}
     4708
     4709void UIGridEditImageType::Draw(QPainter *p, int drawlayer, int context)
     4710{
     4711    if (pmap.isNull())
     4712    {
     4713        QColor drawcolor = QColor( 0, 0, 0);
     4714        p->setBrush(QBrush(Qt::SolidPattern));
     4715        p->setPen(QPen(drawcolor, 2));
     4716        p->drawRect(screen_area);
     4717    }
     4718    else
     4719    {
     4720        p->drawPixmap(screen_area, pmap);
     4721
     4722        p->setBrush(QBrush(Qt::NoBrush));
     4723        // Draw the frame outline
     4724        // This may be covered by the cut indicator
     4725        // Or the highlight
     4726 
     4727        p->setPen(QPen(colorSet[0], 3));
     4728        p->drawRect(outer_border);
     4729
     4730        if (cutStatus > 0)
     4731        {
     4732            p->setPen(QPen(colorSet[cutStatus], 3));
     4733            p->drawRect(inner_border);
     4734            p->drawLine(inner_border.topLeft(), inner_border.bottomRight());
     4735            p->drawLine(inner_border.bottomLeft(), inner_border.topRight());
     4736        }
     4737        if (highlightFrame)
     4738        {
     4739            // Overlay the image frame with the standard frame color
     4740            // This is used to highlight small frame #0
     4741            p->setPen(QPen(highlightColor, 3));
     4742            p->drawRect(outer_border);
     4743        }
     4744    }
     4745}
     4746
     4747void UIGridEditImageType::setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus)
     4748{
     4749    // We can get a null new_pmap at the start or end of the video
     4750    if (! new_pmap)
     4751    {
     4752        clearPixmap();
     4753        return;
     4754    }
     4755
     4756    if (frame == framenumber)
     4757    {
     4758        // No change in pixmap (?)
     4759        setCutStatus(new_cutStatus);
     4760        return;
     4761    }
     4762
     4763    pmap = *new_pmap;
     4764    framenumber = frame;
     4765
     4766    if (new_cutStatus >= 0 && new_cutStatus <= 3)
     4767        cutStatus = new_cutStatus;
     4768    else
     4769        cutStatus = 0;
     4770
     4771    refresh();
     4772}
     4773
     4774void UIGridEditImageType::clearPixmap(bool dorefresh)
     4775{
     4776    if (! pmap.isNull())
     4777    {
     4778        pmap = QPixmap();
     4779
     4780        cutStatus = 0;
     4781        framenumber = -1;
     4782        if (dorefresh)
     4783            refresh();
     4784    }
     4785}
     4786
     4787void UIGridEditImageType::setCutStatus(int new_cutStatus)
     4788{
     4789    if (new_cutStatus == cutStatus)
     4790        return;
     4791
     4792    if (new_cutStatus >= 0 && new_cutStatus <= 3)
     4793        cutStatus = new_cutStatus;
     4794    else
     4795        cutStatus = 0;
     4796
     4797    refresh();
     4798}
     4799
     4800// ********************************************************************
     4801
     4802UIGridEditSliderType::UIGridEditSliderType(const QString &name)
     4803                     : UIType(name)
     4804{
     4805    m_drawMap = NULL;
     4806    m_position=0;
     4807}
     4808
     4809void UIGridEditSliderType::calculateScreenArea()
     4810{
     4811    QRect r = area;
     4812    r.translate(m_parent->GetAreaRect().left(),
     4813                m_parent->GetAreaRect().top());
     4814    screen_area = r;
     4815
     4816    if (m_drawMap)
     4817        delete [] m_drawMap;
     4818
     4819    m_drawWidth = area.width();
     4820    m_drawMap = new unsigned char[m_drawWidth];
     4821    for (int i = 0; i < m_drawWidth; i++)
     4822        m_drawMap[i] = 0;
     4823}
     4824
     4825void UIGridEditSliderType::ClearAll()
     4826{
     4827    for (int i = 0; i < m_drawWidth; i++)
     4828        m_drawMap[i] = 0;
     4829    refresh();
     4830}
     4831
     4832void UIGridEditSliderType::SetRange(
     4833        long long fstart, long long fend, long long fcount)
     4834{
     4835    if (fcount <= 0)
     4836    {
     4837        VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1")
     4838                .arg(fcount));
     4839        return;
     4840    }
     4841    if (fstart < 0)
     4842    {
     4843        VERBOSE(VB_IMPORTANT, QString("Invalid starting frame: %1")
     4844                .arg(fstart));
     4845        return;
     4846    }
     4847    if (fend < 0)
     4848    {
     4849        VERBOSE(VB_IMPORTANT, QString("Invalid ending frame: %1")
     4850                .arg(fend));
     4851        return;
     4852    }
     4853
     4854    if (fstart > fcount) fstart = fcount;
     4855    if (fend > fcount) fend = fcount;
     4856
     4857    int start = (int)((1.0 * fstart * m_drawWidth) / fcount);
     4858    int end   = (int)((1.0 * fend   * m_drawWidth) / fcount);
     4859
     4860    if (start < 0)
     4861        start = 0;
     4862    if (start >= m_drawWidth)
     4863        start = m_drawWidth - 1;
     4864    if (end < 0)
     4865        end = 0;
     4866    if (end >= m_drawWidth)
     4867        end = m_drawWidth - 1;
     4868
     4869    if (end < start)
     4870    {
     4871        int tmp = start;
     4872        start = end;
     4873        end = tmp;
     4874    }
     4875
     4876    for (int i = start; i < end; i++)
     4877        if (m_drawMap[i] < 1)
     4878            m_drawMap[i] = 1;
     4879
     4880    // Mark endpoints
     4881    m_drawMap[start] = 2;
     4882    m_drawMap[end]   = 2;
     4883
     4884    VERBOSE(VB_GENERAL, QString("Range = %1 - %2 (%3 - %4)")
     4885            .arg(start).arg(end)
     4886            .arg(fstart).arg(fend));
     4887    refresh();
     4888}
     4889
     4890void UIGridEditSliderType::SetPosition(
     4891        long long fposition, long long fcount)
     4892{
     4893    if (fcount <= 0)
     4894    {
     4895        VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1")
     4896                .arg(fcount));
     4897        return;
     4898    }
     4899
     4900    if (fposition < 0)
     4901    {
     4902        VERBOSE(VB_IMPORTANT, QString("Invalid position frame: %1")
     4903                .arg(fposition));
     4904        return;
     4905    }
     4906
     4907    if (fposition > fcount) fposition = fcount;
     4908
     4909    int new_position = (int)(1.0 * fposition * m_drawWidth) / fcount;
     4910
     4911    if (new_position < 0)
     4912        new_position = 0;
     4913    if (new_position >= m_drawWidth)
     4914       new_position = m_drawWidth - 1;
     4915
     4916    if (new_position != m_position)
     4917    {
     4918        m_position = new_position;
     4919        refresh();
     4920    }
     4921}
     4922
     4923void UIGridEditSliderType::Draw(QPainter *p, int drawlayer, int context)
     4924{
     4925    // Draw Background
     4926    p->setPen(QPen(colorSet[0], 2));
     4927    p->setBrush(colorSet[0]);
     4928    p->drawRect(screen_area);
     4929
     4930    // Draw bars
     4931
     4932//    VERBOSE(VB_GENERAL, QString("Starting"));
     4933    int i = 0;
     4934    do {
     4935        int start = 0;
     4936        int end = 0;
     4937
     4938        while (i < m_drawWidth && m_drawMap[i] == 0) i++;
     4939        if (i == m_drawWidth) break;
     4940        start = i;
     4941
     4942        i++;
     4943       
     4944
     4945        while (i < m_drawWidth && m_drawMap[i] == 1) i++;
     4946        end = i;
     4947        if (end == m_drawWidth) end--;
     4948
     4949        // If the next map value is not a normal internal cutpoint
     4950        // increment i so we handle it properly
     4951        if (end+1 < m_drawWidth && m_drawMap[end+1] != 1)
     4952            i++;
     4953
     4954        // start == starting point
     4955        //   end == endingpoint
     4956        {
     4957            QRect r = screen_area;
     4958            r.setLeft(r.left() + start);
     4959            r.setWidth(end - start);
     4960
     4961//            VERBOSE(VB_GENERAL, QString("Cut from (%1, %2) - (%3, %4)")
     4962//                    .arg(r.left()).arg(r.top())
     4963//                    .arg(r.right()).arg(r.bottom()));
     4964
     4965//            VERBOSE(VB_GENERAL, QString("start = %1, m_position = %2, end = %3")
     4966//                    .arg(start)
     4967//                    .arg(m_position)
     4968//                    .arg(end));
     4969           
     4970            if (start <= m_position && m_position <= end)
     4971            {
     4972                p->setPen(QPen(colorSet[4], 2));
     4973                p->setBrush(colorSet[4]);
     4974            }
     4975            else
     4976            {
     4977                p->setPen(QPen(colorSet[1], 2));
     4978                p->setBrush(colorSet[1]);
     4979            }
     4980            p->drawRect(r);
     4981
     4982            p->setPen(QPen(colorSet[2], 2));
     4983            p->setBrush(colorSet[2]);
     4984            if (m_drawMap[start] == 2)
     4985                p->drawLine(r.topLeft(), r.bottomLeft());
     4986            if (m_drawMap[end] == 2)
     4987                p->drawLine(r.topRight(), r.bottomRight());
     4988
     4989        }
     4990    } while (i < m_drawWidth);
     4991
     4992    // Draw Current Position Mark
     4993
     4994    QPoint ptop(screen_area.left() + m_position, screen_area.top());
     4995    QPoint pbot(screen_area.left() + m_position, screen_area.bottom());
     4996
     4997    p->setPen(QPen(colorSet[3], 2));
     4998    p->setBrush(colorSet[3]);
     4999    p->drawLine(ptop, pbot);
     5000}
     5001
     5002// ********************************************************************
     5003
    46865004UIKeyType::UIKeyType(const QString &name)
    46875005         : UIType(name)
    46885006{
  • mythtv/libs/libmyth/uitypes.h

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/uitypes.h myth.20155.0309b/mythtv/libs/libmyth/uitypes.h
     
    11721172    QRect area;
    11731173};
    11741174
     1175class MPUBLIC UIGridEditImageType : public UIType
     1176{
     1177    Q_OBJECT
     1178
     1179  public:
     1180
     1181    UIGridEditImageType(const QString &name);
     1182    void calculateScreenArea();
     1183    void setArea(QRect an_area)     { area = an_area; };
     1184
     1185    void setOutlineColor(QColor c)  { colorSet[0] = c; };
     1186    void setCutColor(QColor c)      { colorSet[1] = c; };
     1187    void setCutPointColor(QColor c)
     1188    {
     1189         colorSet[2] = c; // Cut before
     1190         colorSet[3] = c; // Cut after
     1191    };
     1192    void setHighlightFrame(bool high) { highlightFrame = high; };
     1193    void setHighlightColor(QColor c)  { highlightColor = c; };
     1194
     1195    virtual void Draw(QPainter *, int, int);
     1196    void setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus);
     1197 
     1198    void clearPixmap(bool dorefresh=true);
     1199    void setCutStatus(int new_cutStatus);
     1200
     1201    QRect getOuterBorder() { return outer_border; };
     1202  protected:
     1203
     1204    QRect    area;
     1205    QRect    inner_border;
     1206    QRect    outer_border;
     1207    QPixmap  pmap;
     1208    long long framenumber; // for consistency checking
     1209    int      cutStatus;
     1210    QColor   colorSet[4];
     1211    bool     highlightFrame;
     1212    QColor   highlightColor;
     1213};
     1214
     1215class MPUBLIC UIGridEditSliderType : public UIType
     1216{
     1217    Q_OBJECT
     1218
     1219  public:
     1220
     1221    UIGridEditSliderType(const QString &name);
     1222    void calculateScreenArea();
     1223    void setArea(QRect an_area)     { area = an_area; };
     1224
     1225    void setFillColor(QColor c)     { colorSet[0] = c; };
     1226    void setCutColor(QColor c)      { colorSet[1] = c; };
     1227    void setCutPointColor(QColor c) { colorSet[2] = c; };
     1228    void setPositionColor(QColor c) { colorSet[3] = c; };
     1229    void setInCutColor(QColor c)    { colorSet[4] = c; };
     1230
     1231    void ClearAll();
     1232    void SetRange(long long fstart, long long fend, long long fcount);
     1233    void SetPosition(long long fposition, long long fcount);
     1234
     1235    virtual void Draw(QPainter *, int, int);
     1236  protected:
     1237
     1238    QRect          area;
     1239    unsigned char *m_drawMap;
     1240    int            m_drawWidth;
     1241    int            m_position;
     1242
     1243    QColor         colorSet[5];
     1244};
     1245
     1246
    11751247class MPUBLIC UIKeyType : public UIType
    11761248{
    11771249    Q_OBJECT
  • mythtv/libs/libmyth/xmlparse.cpp

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/xmlparse.cpp myth.20155.0309b/mythtv/libs/libmyth/xmlparse.cpp
     
    13631363            {
    13641364                parseBlackHole(container, info);
    13651365            }
     1366            else if (info.tagName() == "grideditimage")
     1367            {
     1368                parseGridEditImage(container, info);
     1369            }
     1370            else if (info.tagName() == "grideditslider")
     1371            {
     1372                parseGridEditSlider(container, info);
     1373            }
    13661374            else if (info.tagName() == "area")
    13671375            {
    13681376                area = parseRect(getFirstText(info));
     
    31263134    container->AddType(bh);
    31273135}
    31283136
     3137
     3138void XMLParse::parseGridEditImage(LayerSet *container, QDomElement &element)
     3139{
     3140    QRect area;
     3141    QColor outlineColor;
     3142    QColor cutColor;
     3143    QColor cutPointColor;
     3144    QColor highlightColor;
     3145    bool   haveOutlineColor = false;
     3146    bool   haveCutColor = false;
     3147    bool   haveCutPointColor = false;
     3148    bool   haveHighlightColor = false;
     3149    bool   highlightFrame = false;
     3150
     3151    QString name = element.attribute("name", "");
     3152    if (name.isNull() || name.isEmpty())
     3153    {
     3154        VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditImage needs a name");
     3155        return;
     3156    }
     3157    QString highlight = element.attribute("highlightframe", "");
     3158    if (highlight == "true")
     3159        highlightFrame = true;
     3160
     3161    for (QDomNode child = element.firstChild(); !child.isNull();
     3162         child = child.nextSibling())
     3163    {
     3164        QDomElement info = child.toElement();
     3165        if (!info.isNull())
     3166        {
     3167            if (info.tagName() == "area")
     3168            {
     3169                area = parseRect(getFirstText(info));
     3170                normalizeRect(area);
     3171            }
     3172            else if (info.tagName() == "outlinecolor")
     3173            {
     3174                haveOutlineColor = true;
     3175                outlineColor = getFirstText(info);
     3176            }
     3177            else if (info.tagName() == "cutcolor")
     3178            {
     3179                haveCutColor = true;
     3180                cutColor = getFirstText(info);
     3181            }
     3182            else if (info.tagName() == "cutpointcolor")
     3183            {
     3184                haveCutPointColor = true;
     3185                cutPointColor = getFirstText(info);
     3186            }
     3187            else if (info.tagName() == "highlightcolor")
     3188            {
     3189                haveHighlightColor = true;
     3190                highlightColor = getFirstText(info);
     3191            }
     3192            else
     3193            {
     3194                VERBOSE(VB_IMPORTANT, LOC_WARN +
     3195                        QString("Unknown tag '%1' in grideditimage '%2'")
     3196                        .arg(info.tagName()).arg(name));
     3197                return;
     3198            }
     3199        }
     3200    }
     3201
     3202    if (!haveOutlineColor)
     3203    {
     3204        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3205                QString("Missing tag 'outlinecolor' in grideditimage '%1'")
     3206                .arg(name));
     3207        return;
     3208    }
     3209
     3210    if (!haveCutColor)
     3211    {
     3212        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3213                QString("Missing tag 'cutcolor' in grideditimage '%1'")
     3214                .arg(name));
     3215        return;
     3216    }
     3217
     3218    if (!haveCutPointColor)
     3219    {
     3220        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3221                QString("Missing tag 'cutpointcolor' in grideditimage '%1'")
     3222                .arg(name));
     3223        return;
     3224    }
     3225
     3226    if (highlightFrame && !haveHighlightColor)
     3227    {
     3228        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3229                QString("highlightframe specified but missing tag 'hightlightcolor' in grideditimage '%1'")
     3230                .arg(name));
     3231        return;
     3232    }
     3233
     3234
     3235    UIGridEditImageType *gei = new UIGridEditImageType(name);
     3236    gei->SetScreen(wmult, hmult);
     3237    gei->setArea(area);
     3238    gei->setOutlineColor(outlineColor);
     3239    gei->setCutColor(cutColor);
     3240    gei->setCutPointColor(cutPointColor);
     3241    gei->setHighlightColor(highlightColor);
     3242    gei->setHighlightFrame(highlightFrame);
     3243    gei->SetParent(container);
     3244    gei->calculateScreenArea();
     3245    gei->clearPixmap(false);
     3246    container->AddType(gei);
     3247}
     3248
     3249void XMLParse::parseGridEditSlider(LayerSet *container, QDomElement &element)
     3250{
     3251    QRect area;
     3252    QColor fillColor;
     3253    QColor cutColor;
     3254    QColor inCutColor;
     3255    QColor cutPointColor;
     3256    QColor positionColor;
     3257    bool   haveFillColor = false;
     3258    bool   haveCutColor = false;
     3259    bool   haveInCutColor = false;
     3260    bool   haveCutPointColor = false;
     3261    bool   havePositionColor = false;
     3262
     3263    QString name = element.attribute("name", "");
     3264    if (name.isNull() || name.isEmpty())
     3265    {
     3266        VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditSlider needs a name");
     3267        return;
     3268    }
     3269
     3270    for (QDomNode child = element.firstChild(); !child.isNull();
     3271         child = child.nextSibling())
     3272    {
     3273        QDomElement info = child.toElement();
     3274        if (!info.isNull())
     3275        {
     3276            if (info.tagName() == "area")
     3277            {
     3278                area = parseRect(getFirstText(info));
     3279                normalizeRect(area);
     3280            }
     3281            else if (info.tagName() == "fillcolor")
     3282            {
     3283                haveFillColor = true;
     3284                fillColor = getFirstText(info);
     3285            }
     3286            else if (info.tagName() == "cutcolor")
     3287            {
     3288                haveCutColor = true;
     3289                cutColor = getFirstText(info);
     3290            }
     3291            else if (info.tagName() == "incutcolor")
     3292            {
     3293                haveInCutColor = true;
     3294                inCutColor = getFirstText(info);
     3295            }
     3296            else if (info.tagName() == "cutpointcolor")
     3297            {
     3298                haveCutPointColor = true;
     3299                cutPointColor = getFirstText(info);
     3300            }
     3301            else if (info.tagName() == "positioncolor")
     3302            {
     3303                havePositionColor = true;
     3304                positionColor = getFirstText(info);
     3305            }
     3306            else
     3307            {
     3308                VERBOSE(VB_IMPORTANT, LOC_WARN +
     3309                        QString("Unknown tag '%1' in grideditslider '%2'")
     3310                        .arg(info.tagName()).arg(name));
     3311                return;
     3312            }
     3313        }
     3314    }
     3315
     3316    if (!haveFillColor)
     3317    {
     3318        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3319                QString("Missing tag 'fillcolor' in grideditslider '%1'")
     3320                .arg(name));
     3321        return;
     3322    }
     3323
     3324    if (!haveCutColor)
     3325    {
     3326        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3327                QString("Missing tag 'cutcolor' in grideditslider '%1'")
     3328                .arg(name));
     3329        return;
     3330    }
     3331
     3332    if (!haveInCutColor)
     3333    {
     3334        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3335                QString("Missing tag 'incutcolor' in grideditslider '%1'")
     3336                .arg(name));
     3337        return;
     3338    }
     3339
     3340    if (!haveCutPointColor)
     3341    {
     3342        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3343                QString("Missing tag 'cutpointcolor' in grideditslider '%1'")
     3344                .arg(name));
     3345        return;
     3346    }
     3347
     3348    if (!havePositionColor)
     3349    {
     3350        VERBOSE(VB_IMPORTANT, LOC_WARN +
     3351                QString("Missing tag 'positioncolor' in grideditslider '%1'")
     3352                .arg(name));
     3353        return;
     3354    }
     3355
     3356    UIGridEditSliderType *ges = new UIGridEditSliderType(name);
     3357    ges->SetScreen(wmult, hmult);
     3358    ges->setArea(area);
     3359    ges->setFillColor(fillColor);
     3360    ges->setCutColor(cutColor);
     3361    ges->setInCutColor(inCutColor);
     3362    ges->setCutPointColor(cutPointColor);
     3363    ges->setPositionColor(positionColor);
     3364    ges->SetParent(container);
     3365    ges->calculateScreenArea();
     3366    container->AddType(ges);
     3367}
     3368
    31293369void XMLParse::parseListBtnArea(LayerSet *container, QDomElement &element)
    31303370{
    31313371    int context = -1;
  • mythtv/libs/libmyth/xmlparse.h

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmyth/xmlparse.h myth.20155.0309b/mythtv/libs/libmyth/xmlparse.h
     
    4747    void parseCheckBox(LayerSet *, QDomElement &);
    4848    void parseSelector(LayerSet *, QDomElement &);
    4949    void parseBlackHole(LayerSet *, QDomElement &);
     50    void parseGridEditImage(LayerSet *, QDomElement &);
     51    void parseGridEditSlider(LayerSet *, QDomElement &);
    5052    void parseListBtnArea(LayerSet *, QDomElement &);
    5153    void parseListTreeArea(LayerSet *, QDomElement &);
    5254    void parseKeyboard(LayerSet *, QDomElement &);
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp myth.20155.0309b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
     
    5555#include "mythverbose.h"
    5656#include "myth_imgconvert.h"
    5757
     58#include "grideditcutpoints.h"
     59
    5860extern "C" {
    5961#include "vbitext/vbi.h"
    6062#include "vsync.h"
     
    166168      decoder_thread_alive(true),   killplayer(false),
    167169      killvideo(false),             livetv(false),
    168170      watchingrecording(false),     editmode(false),
     171      hideedits(false),
    169172      resetvideo(false),            using_null_videoout(false),
    170173      no_audio_in(false),           no_audio_out(false),
    171174      transcoding(false),
     
    175178      bookmarkseek(0),              previewFromBookmark(false),
    176179      // Seek
    177180      fftime(0),                    seekamountpos(4),
    178       seekamount(30),               exactseeks(false),
     181      allow_pagesize(false),        half_page(0),
     182      seekamount(30),               seekamounttext("30 Frames"),
     183      exactseeks(false),
    179184      // Playback misc.
    180185      videobuf_retries(0),          framesPlayed(0),
    181186      totalFrames(0),               totalLength(0),
     
    225230      yuv_need_copy(false),         yuv_desired_size(0,0),
    226231      yuv_scaler(NULL),             yuv_frame_scaled(NULL),
    227232      yuv_scaler_in_size(0,0),      yuv_scaler_out_size(0,0),
     233      // Grid Editing
     234      grid_edit_image_scaler(NULL), grid_edit_image_small_scaler(NULL),
     235      grid_edit_image_buffer_yuv(NULL), grid_edit_image_small_buffer_yuv(NULL),
     236      grid_edit_image_buffer_rgb(NULL), grid_edit_image_small_buffer_rgb(NULL),
     237      grid_edit_image_buffer_length(0), grid_edit_image_small_buffer_length(0),
     238      grid_edit_image_in_size(-1, -1),
     239
    228240      // Filters
    229241      videoFiltersForProgram(""),   videoFiltersOverride(""),
    230242      postfilt_width(0),            postfilt_height(0),
     
    371383        output_jmeter = NULL;
    372384    }
    373385
     386    ClearScreenGrab();
     387
    374388    ShutdownYUVResize();
    375389}
    376390
     
    16051619    return retval;
    16061620}
    16071621
     1622
     1623bool NuppelVideoPlayer::GetScreenGrabsOfCurrentFrame(QImage &normal, QImage &small)
     1624{
     1625
     1626    unsigned char *data      = NULL;
     1627    VideoFrame    *frame     = NULL;
     1628    AVPicture      orig;
     1629    AVPicture      scaled;
     1630    AVPicture      scaled_small;
     1631    bzero(&orig,         sizeof(AVPicture));
     1632    bzero(&scaled,       sizeof(AVPicture));
     1633    bzero(&scaled_small, sizeof(AVPicture));
     1634
     1635    int vw, vh;
     1636    if (!(frame = GetCurrentFrame(vw, vh)))
     1637    {
     1638        return false;
     1639    }
     1640
     1641    if (!(data = frame->buf))
     1642    {
     1643        ReleaseCurrentFrame(frame);
     1644        return false;
     1645    }
     1646
     1647    // Check to see if the screen dimensions have changed
     1648    // Probably shouldn't happen in normal use.
     1649    if (grid_edit_image_in_size != video_dim)
     1650        SetupScreenGrab();
     1651
     1652    avpicture_fill(&orig, data, PIX_FMT_YUV420P,
     1653                   video_dim.width(), video_dim.height());
     1654
     1655    avpicture_deinterlace(&orig, &orig, PIX_FMT_YUV420P,
     1656                          video_dim.width(), video_dim.height());
     1657
     1658    // Rescale to the normal size
     1659    avpicture_fill(&scaled, grid_edit_image_buffer_yuv, PIX_FMT_YUV420P,
     1660                   grid_edit_image_size.width(),
     1661                   grid_edit_image_size.height());
     1662
     1663    img_resample(grid_edit_image_scaler, &scaled, &orig);
     1664
     1665    // Don't need the current frame anymore so release it
     1666    ReleaseCurrentFrame(frame);
     1667
     1668    // Rescale to the small size
     1669    avpicture_fill(&scaled_small, grid_edit_image_small_buffer_yuv, PIX_FMT_YUV420P,
     1670                   grid_edit_image_small_size.width(),
     1671                   grid_edit_image_small_size.height());
     1672
     1673    img_resample(grid_edit_image_small_scaler, &scaled_small, &scaled);
     1674
     1675    // Convert scaled and scaled_small from YUV to RGB
     1676
     1677    // scaled first
     1678    uint w = grid_edit_image_size.width();
     1679    uint h = grid_edit_image_size.height();
     1680    unsigned char *yuv_buf = grid_edit_image_buffer_yuv;
     1681    unsigned char *rgb_buf = grid_edit_image_buffer_rgb;
     1682    yuv2argb_conv(rgb_buf,
     1683                  yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
     1684                  w, h, w * 4, w, w / 2, 0);
     1685
     1686    // scaled_small next
     1687    w = grid_edit_image_small_size.width();
     1688    h = grid_edit_image_small_size.height();
     1689    yuv_buf = grid_edit_image_small_buffer_yuv;
     1690    rgb_buf = grid_edit_image_small_buffer_rgb;
     1691    yuv2argb_conv(rgb_buf,
     1692                  yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
     1693                  w, h, w * 4, w, w / 2, 0);
     1694
     1695#ifdef MMX
     1696#define _RGBSWAP .rgbSwapped()
     1697#endif
     1698
     1699    normal = QImage(grid_edit_image_buffer_rgb,
     1700                    grid_edit_image_size.width(), grid_edit_image_size.height(),
     1701                    QImage::Format_RGB32)_RGBSWAP;
     1702
     1703    small = QImage(grid_edit_image_small_buffer_rgb,
     1704                   grid_edit_image_small_size.width(), grid_edit_image_small_size.height(),
     1705                   QImage::Format_RGB32)_RGBSWAP;
     1706
     1707    return true;
     1708}
     1709
     1710void NuppelVideoPlayer::SetScreenGrabSizes(QSize normal, QSize small)
     1711{
     1712    grid_edit_image_size = normal;
     1713    grid_edit_image_small_size = small;
     1714
     1715    SetupScreenGrab();
     1716    VERBOSE(VB_GENERAL, QString("Main Image = (%1, %2) from (%3, %4)")
     1717                        .arg(grid_edit_image_size.width())
     1718                        .arg(grid_edit_image_size.height())
     1719                        .arg(normal.width()).arg(normal.height()));
     1720    VERBOSE(VB_GENERAL, QString("Small Image = (%1, %2) from (%3, %4)")
     1721                        .arg(grid_edit_image_small_size.width())
     1722                        .arg(grid_edit_image_small_size.height())
     1723                        .arg(small.width()).arg(small.height()));
     1724
     1725}
     1726
     1727void NuppelVideoPlayer::ClearScreenGrab()
     1728{
     1729    if (grid_edit_image_scaler)
     1730    {
     1731        img_resample_close(grid_edit_image_scaler);
     1732        grid_edit_image_scaler = NULL;
     1733    }
     1734
     1735    if (grid_edit_image_small_scaler)
     1736    {
     1737        img_resample_close(grid_edit_image_small_scaler);
     1738        grid_edit_image_small_scaler=NULL;
     1739    }
     1740
     1741    if (grid_edit_image_buffer_yuv)
     1742    {
     1743        delete grid_edit_image_buffer_yuv;
     1744        grid_edit_image_buffer_yuv=NULL;
     1745    }
     1746
     1747    if (grid_edit_image_small_buffer_yuv)
     1748    {
     1749        delete grid_edit_image_small_buffer_yuv;
     1750        grid_edit_image_small_buffer_yuv=NULL;
     1751    }
     1752
     1753    if (grid_edit_image_buffer_rgb)
     1754    {
     1755        delete grid_edit_image_buffer_rgb;
     1756        grid_edit_image_buffer_rgb=NULL;
     1757    }
     1758
     1759    if (grid_edit_image_small_buffer_rgb)
     1760    {
     1761        delete grid_edit_image_small_buffer_rgb;
     1762        grid_edit_image_small_buffer_rgb=NULL;
     1763    }
     1764}
     1765
     1766void NuppelVideoPlayer::SetupScreenGrab()
     1767{
     1768    ClearScreenGrab();
     1769    grid_edit_image_in_size = video_dim;
     1770
     1771    // Normalize the output sizes.
     1772    // This is necessary to preserve the aspect ratio
     1773
     1774    QSize tmpsize = grid_edit_image_size;
     1775    grid_edit_image_size =  video_dim;
     1776    grid_edit_image_size.scale(tmpsize, Qt::KeepAspectRatio);
     1777
     1778    tmpsize = grid_edit_image_small_size;
     1779    grid_edit_image_small_size = video_dim;
     1780    grid_edit_image_small_size.scale(tmpsize, Qt::KeepAspectRatio);
     1781
     1782    grid_edit_image_size = QSize(grid_edit_image_size.width() & ~0x7,
     1783                                 grid_edit_image_size.height() & ~0x7);
     1784    grid_edit_image_small_size = QSize(grid_edit_image_small_size.width() & ~0x7,
     1785                                       grid_edit_image_small_size.height() & ~0x7);
     1786
     1787    // Do normal first
     1788    uint sz = grid_edit_image_size.width() * grid_edit_image_size.height();
     1789    grid_edit_image_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128];
     1790    grid_edit_image_buffer_rgb = new unsigned char[sz * 4 + 128];
     1791
     1792    grid_edit_image_scaler = img_resample_init(
     1793                grid_edit_image_size.width(), grid_edit_image_size.height(),
     1794                grid_edit_image_in_size.width(),  grid_edit_image_in_size.height());
     1795
     1796    // Then small
     1797    sz = grid_edit_image_small_size.width() * grid_edit_image_small_size.height();
     1798    grid_edit_image_small_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128];
     1799    grid_edit_image_small_buffer_rgb = new unsigned char[sz * 4 + 128];
     1800
     1801    // Resize from normal to small
     1802    grid_edit_image_small_scaler = img_resample_init(
     1803                grid_edit_image_small_size.width(), grid_edit_image_small_size.height(),
     1804                grid_edit_image_size.width(),  grid_edit_image_size.height());
     1805}
     1806
    16081807void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame)
    16091808{
    16101809    if (frame)
     
    49885187
    49895188    dialogname = "";
    49905189
     5190    osd->HideAllExcept("editmode");
     5191
    49915192    QMap<QString, QString> infoMap;
    49925193    player_ctx->LockPlayingInfo(__FILE__, __LINE__);
    49935194    player_ctx->playingInfo->ToMap(infoMap);
     
    50525253    player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
    50535254}
    50545255
     5256bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame)
     5257{
     5258    bool tmpexactseeks = exactseeks;
     5259    GetDecoder()->setExactSeeks(true);
     5260
     5261//    VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2")
     5262//           .arg(GetFramesPlayed())
     5263//           .arg(targetFrame));
     5264
     5265    if (framesPlayed > targetFrame)
     5266    {
     5267        // seek back
     5268        rewindtime = framesPlayed - targetFrame;
     5269        while (rewindtime != 0)
     5270            usleep(1000);
     5271    }
     5272    else
     5273    {
     5274        // seek forward
     5275        fftime = targetFrame - framesPlayed;
     5276        while (fftime != 0)
     5277            usleep(1000);
     5278
     5279    }
     5280//    VERBOSE(VB_GENERAL, QString("After current frame = %1")
     5281//           .arg(GetFramesPlayed()));
     5282    GetDecoder()->setExactSeeks(tmpexactseeks);
     5283    return (targetFrame == framesPlayed);
     5284}
     5285
     5286void NuppelVideoPlayer::EditHandleClearMap()
     5287{
     5288    QMap<long long, int>::Iterator it;
     5289    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5290        osd->HideEditArrow(it.key(), *it);
     5291
     5292    deleteMap.clear();
     5293    UpdateEditSlider();
     5294}
     5295
     5296void NuppelVideoPlayer::EditHandleInvertMap()
     5297{
     5298    QMap<long long, int>::Iterator it;
     5299    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5300        ReverseMark(it.key());
     5301
     5302    UpdateEditSlider();
     5303    UpdateTimeDisplay();
     5304}
     5305
     5306void NuppelVideoPlayer::EditHandleLoadCommSkip()
     5307{
     5308    if (hascommbreaktable)
     5309    {
     5310        commBreakMapLock.lock();
     5311        QMap<long long, int>::Iterator it;
     5312        for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it)
     5313        {
     5314            if (!deleteMap.contains(it.key()))
     5315            {
     5316                if (*it == MARK_COMM_START)
     5317                    AddMark(it.key(), MARK_CUT_START);
     5318                else
     5319                    AddMark(it.key(), MARK_CUT_END);
     5320            }
     5321        }
     5322        commBreakMapLock.unlock();
     5323        UpdateEditSlider();
     5324        UpdateTimeDisplay();
     5325    }
     5326}
     5327
    50555328bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e)
    50565329{
    50575330    bool handled = false;
     
    51315404            UpdateTimeDisplay();
    51325405        }
    51335406        else if (action == "CLEARMAP")
    5134         {
    5135             QMap<long long, int>::Iterator it;
    5136             for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
    5137                 osd->HideEditArrow(it.key(), *it);
    5138 
    5139             deleteMap.clear();
    5140             UpdateEditSlider();
    5141         }
     5407            EditHandleClearMap();
    51425408        else if (action == "INVERTMAP")
    5143         {
    5144             QMap<long long, int>::Iterator it;
    5145             for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
    5146                 ReverseMark(it.key());
    5147 
    5148             UpdateEditSlider();
    5149             UpdateTimeDisplay();
    5150         }
     5409            EditHandleInvertMap();
    51515410        else if (action == "LOADCOMMSKIP")
    5152         {
    5153             if (hascommbreaktable)
    5154             {
    5155                 commBreakMapLock.lock();
    5156                 QMap<long long, int>::Iterator it;
    5157                 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it)
    5158                 {
    5159                     if (!deleteMap.contains(it.key()))
    5160                     {
    5161                         if (*it == MARK_COMM_START)
    5162                             AddMark(it.key(), MARK_CUT_START);
    5163                         else
    5164                             AddMark(it.key(), MARK_CUT_END);
    5165                     }
    5166                 }
    5167                 commBreakMapLock.unlock();
    5168                 UpdateEditSlider();
    5169                 UpdateTimeDisplay();
    5170             }
    5171         }
     5411            EditHandleLoadCommSkip();
    51725412        else if (action == "PREVCUT")
    51735413        {
    51745414            int old_seekamount = seekamount;
     
    52145454            UpdateEditSlider();
    52155455            UpdateTimeDisplay();
    52165456        }
    5217         else if (action == "ESCAPE" || action == "MENU" ||
    5218                  action == "TOGGLEEDIT")
     5457        else if (action == "TOGGLEEDIT" || action == "MENU")
     5458              m_tv->ShowEditRecordingGrid();
     5459        else if (action == "ESCAPE")
    52195460        {
    52205461            DisableEdit();
    52215462            retval = false;
     
    52285469    return retval;
    52295470}
    52305471
     5472void NuppelVideoPlayer::ShowEditRecordingGrid(void)
     5473{
     5474    // Completely hide the OSD
     5475    osd->HideAll();
     5476    hideedits = true;
     5477
     5478    GridEditCutpoints::Run(this);
     5479
     5480    ClearScreenGrab();
     5481
     5482    allow_pagesize = false;
     5483    hideedits = false;
     5484
     5485    // Show OSD
     5486
     5487    QMap<QString, QString> infoMap;
     5488    player_ctx->LockPlayingInfo(__FILE__, __LINE__);
     5489    player_ctx->playingInfo->ToMap(infoMap);
     5490    infoMap.detach();
     5491    player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
     5492
     5493    osd->SetText("editmode", infoMap, -1);
     5494
     5495    UpdateEditSlider();
     5496    UpdateTimeDisplay();
     5497    if (seekamountpos == 3 || seekamountpos == 4)
     5498        UpdateSeekAmount(true);
     5499    else
     5500        UpdateSeekAmountDisplay();
     5501
     5502    QMap<long long, int>::Iterator it;
     5503    for (it = deleteMap.begin(); it != deleteMap.end(); ++it)
     5504         AddMark(it.key(), *it);
     5505}
     5506
    52315507AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const
    52325508{
    52335509    if (videoOutput)
     
    53045580
    53055581void NuppelVideoPlayer::UpdateSeekAmount(bool up)
    53065582{
    5307     if (seekamountpos > 0 && !up)
    5308         seekamountpos--;
    5309     if (seekamountpos < 9 && up)
    5310         seekamountpos++;
     5583    if (up)
     5584    {
     5585        if (seekamountpos < 11)
     5586            seekamountpos++;
     5587        if (allow_pagesize)
     5588        {
     5589            if (seekamountpos == 1)
     5590                seekamountpos = 2;
     5591        }
     5592        else
     5593        {
     5594            if (seekamountpos == 3 || seekamountpos == 4)
     5595                seekamountpos = 5;
     5596        }
     5597    }
     5598    else
     5599    {
     5600        if (seekamountpos > 0)
     5601            seekamountpos--;
     5602        if (allow_pagesize)
     5603        {
     5604            if (seekamountpos == 1)
     5605                seekamountpos =0;
     5606        }
     5607        else
     5608        {
     5609            if (seekamountpos == 3 || seekamountpos == 4)
     5610                seekamountpos = 2;
     5611        }
     5612    }
    53115613
    53125614    QString text = "";
    53135615
    53145616    switch (seekamountpos)
    53155617    {
    5316         case 0: text = QObject::tr("cut point"); seekamount = -2; break;
    5317         case 1: text = QObject::tr("keyframe"); seekamount = -1; break;
    5318         case 2: text = QObject::tr("1 frame"); seekamount = 1; break;
    5319         case 3: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break;
    5320         case 4: text = QObject::tr("%n second(s)", "", 1); seekamount = (int)roundf(video_frame_rate); break;
    5321         case 5: text = QObject::tr("%n second(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 5); break;
    5322         case 6: text = QObject::tr("%n second(s)", "", 20); seekamount = (int)roundf(video_frame_rate * 20); break;
    5323         case 7: text = QObject::tr("%n minute(s)", "", 1); seekamount = (int)roundf(video_frame_rate * 60); break;
    5324         case 8: text = QObject::tr("%n minute(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 300); break;
    5325         case 9: text = QObject::tr("%n minute(s)", "", 10); seekamount = (int)roundf(video_frame_rate * 600); break;
     5618        case  0: text = QObject::tr("cut point"); seekamount = -2; break;
     5619
     5620        // Only for non-edit grid
     5621        case  1: text = QObject::tr("keyframe"); seekamount = -1; break;
     5622        // Only for non-edit grid
     5623
     5624        case  2: text = QObject::tr("1 frame"); seekamount = 1; break;
     5625
     5626        // Case 3 & 4 are for the edit grid only
     5627        case  3: text = QObject::tr("1/2 Page");    seekamount =  half_page; break;
     5628        case  4: text = QObject::tr("Full Page");   seekamount =  2*half_page; break;
     5629        // Case 3 & 4 are for the edit grid only
     5630   
     5631        case  5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break;
     5632        case  6: text = QObject::tr("%n second(s)", "", 1); seekamount = (int)roundf(video_frame_rate); break;
     5633        case  7: text = QObject::tr("%n second(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 5); break;
     5634        case  8: text = QObject::tr("%n second(s)", "", 20); seekamount = (int)roundf(video_frame_rate * 20); break;
     5635        case  9: text = QObject::tr("%n minute(s)", "", 1); seekamount = (int)roundf(video_frame_rate * 60); break;
     5636        case 10: text = QObject::tr("%n minute(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 300); break;
     5637        case 11: text = QObject::tr("%n minute(s)", "", 10); seekamount = (int)roundf(video_frame_rate * 600); break;
    53265638        default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break;
    53275639    }
    53285640
     5641    seekamounttext = text;
     5642    UpdateSeekAmountDisplay();
     5643}
     5644
     5645void NuppelVideoPlayer::UpdateSeekAmountDisplay(void)
     5646{
    53295647    QMap<QString, QString> infoMap;
    5330     infoMap["seekamount"] = text;
    5331     osd->SetText("editmode", infoMap, -1);
     5648    infoMap["seekamount"] = seekamounttext;
     5649    if (!hideedits)
     5650        osd->SetText("editmode", infoMap, -1);
    53325651}
    53335652
    53345653void NuppelVideoPlayer::UpdateTimeDisplay(void)
     
    53585677    infoMap["timedisplay"] = timestr;
    53595678    infoMap["framedisplay"] = framestr;
    53605679    infoMap["cutindicator"] = cutmarker;
    5361     osd->SetText("editmode", infoMap, -1);
     5680    if (!hideedits)
     5681        osd->SetText("editmode", infoMap, -1);
    53625682}
    53635683
    5364 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)
     5684DeletePointInfo NuppelVideoPlayer::GetDeletePointInfo(long long frame, bool allowSelectNear)
    53655685{
    5366     bool deletepoint = false;
    5367     bool cut_after = false;
    5368     int direction = 0;
     5686    DeletePointInfo retval;
    53695687
    53705688    if(!deleteMap.isEmpty())
    53715689    {
    53725690        QMap<long long, int>::ConstIterator iter = deleteMap.begin();
    53735691
    5374         while((iter != deleteMap.end()) && (iter.key() < framesPlayed))
     5692        while((iter != deleteMap.end()) && (iter.key() < frame))
    53755693            ++iter;
    53765694
    53775695        if (iter == deleteMap.end())
    53785696        {
    53795697            --iter;
    5380             cut_after = !(*iter);
     5698            retval.cut_after = !(*iter);
    53815699        }
    5382         else if((iter != deleteMap.begin()) && (iter.key() != framesPlayed))
     5700        else if((iter != deleteMap.begin()) && (iter.key() != frame))
    53835701        {
    53845702            long long value = iter.key();
    5385             if((framesPlayed - (--iter).key()) > (value - framesPlayed))
     5703            if((framesPlayed - (--iter).key()) > (value - frame))
    53865704            {
    5387                 cut_after = !(*iter);
     5705                retval.cut_after = !(*iter);
    53885706                ++iter;
    53895707            }
    53905708            else
    5391                 cut_after = !(*iter);
     5709                retval.cut_after = !(*iter);
    53925710        }
    53935711
    5394         direction = (*iter);
    5395         deleteframe = iter.key();
     5712        retval.direction = (*iter);
     5713        retval.deleteframe = iter.key();
    53965714
    5397         if ((absLongLong(deleteframe - framesPlayed) <
     5715        if ((absLongLong(retval.deleteframe - frame) <
    53985716                   (int)ceil(20 * video_frame_rate)) && !allowSelectNear)
    53995717        {
    5400             deletepoint = true;
     5718            retval.deletepoint = true;
    54015719        }
    54025720    }
     5721    return retval;
     5722}
    54035723
    5404     if (deletepoint)
     5724void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)
     5725{
     5726    DeletePointInfo dpi = GetDeletePointInfo(framesPlayed, allowSelectNear);
     5727    deleteframe = dpi.deleteframe;
     5728
     5729    if (dpi.deletepoint)
    54055730    {
    54065731        QString message = QObject::tr("You are close to an existing cut point. "
    54075732                                      "Would you like to:");
     
    54095734        QString option2 = QObject::tr("Move this cut point to the current "
    54105735                                      "position");
    54115736        QString option3 = QObject::tr("Flip directions - delete to the ");
    5412         if (direction == 0)
     5737        if (dpi.direction == 0)
    54135738            option3 += QObject::tr("right");
    54145739        else
    54155740            option3 += QObject::tr("left");
     
    54395764        options += option1;
    54405765        options += option2;
    54415766
    5442         osd->NewDialogBox(dialogname, message, options, -1, cut_after);
     5767        osd->NewDialogBox(dialogname, message, options, -1, dpi.cut_after);
    54435768    }
    54445769}
    54455770
     
    54905815
    54915816void NuppelVideoPlayer::UpdateEditSlider(void)
    54925817{
    5493     osd->DoEditSlider(deleteMap, framesPlayed, totalFrames);
     5818    if (!hideedits)
     5819        osd->DoEditSlider(deleteMap, framesPlayed, totalFrames);
    54945820}
    54955821
    54965822void NuppelVideoPlayer::AddMark(long long frames, int type)
    54975823{
    54985824    deleteMap[frames] = type;
    5499     osd->ShowEditArrow(frames, totalFrames, type);
     5825    if (!hideedits)
     5826        osd->ShowEditArrow(frames, totalFrames, type);
    55005827}
    55015828
    55025829void NuppelVideoPlayer::DeleteMark(long long frames)
    55035830{
    5504     osd->HideEditArrow(frames, deleteMap[frames]);
     5831    if (!hideedits)
     5832        osd->HideEditArrow(frames, deleteMap[frames]);
    55055833    deleteMap.remove(frames);
    55065834}
    55075835
    55085836void NuppelVideoPlayer::ReverseMark(long long frames)
    55095837{
    5510     osd->HideEditArrow(frames, deleteMap[frames]);
     5838    if (!hideedits)
     5839        osd->HideEditArrow(frames, deleteMap[frames]);
    55115840
    55125841    if (deleteMap[frames] == MARK_CUT_END)
    55135842        deleteMap[frames] = MARK_CUT_START;
    55145843    else
    55155844        deleteMap[frames] = MARK_CUT_END;
    55165845
    5517     osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]);
     5846    if (!hideedits)
     5847        osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]);
     5848}
     5849
     5850long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right)
     5851{
     5852    QMap<long long, int>::Iterator i = deleteMap.begin();                                     
     5853    long long framenum = -1;
     5854    long long seekcount = 0;
     5855    if (right)                                                                                 
     5856    {
     5857        for (; i != deleteMap.end(); ++i)                                                     
     5858        {
     5859            if (i.key() > baseframe)                                                       
     5860            {
     5861                framenum = i.key();                                                           
     5862                break;                                                                         
     5863            }                                                                                 
     5864        }                                                                                     
     5865        if (framenum == -1)
     5866            framenum = totalFrames;
     5867        seekcount = framenum - baseframe;
     5868    }
     5869    else
     5870    {
     5871        for (; i != deleteMap.end(); ++i)
     5872        {
     5873            if (i.key() >= baseframe)
     5874                break;
     5875            framenum = i.key();
     5876        }
     5877        if (framenum == -1)
     5878            framenum = 0;
     5879        seekcount = baseframe - framenum;
     5880    }
     5881    return seekcount;
    55185882}
    55195883
    55205884void NuppelVideoPlayer::HandleArbSeek(bool right)
    55215885{
    55225886    if (seekamount == -2)
    55235887    {
    5524         QMap<long long, int>::Iterator i = deleteMap.begin();
    5525         long long framenum = -1;
     5888        long long seekcount = CalcCutPointSeek(framesPlayed, right);
    55265889        if (right)
    55275890        {
    5528             for (; i != deleteMap.end(); ++i)
    5529             {
    5530                 if (i.key() > framesPlayed)
    5531                 {
    5532                     framenum = i.key();
    5533                     break;
    5534                 }
    5535             }
    5536             if (framenum == -1)
    5537                 framenum = totalFrames;
    5538 
    5539             fftime = framenum - framesPlayed;
     5891            fftime = seekcount;
    55405892            while (fftime > 0)
    55415893                usleep(1000);
    55425894        }
    55435895        else
    55445896        {
    5545             for (; i != deleteMap.end(); ++i)
    5546             {
    5547                 if (i.key() >= framesPlayed)
    5548                     break;
    5549                 framenum = i.key();
    5550             }
    5551             if (framenum == -1)
    5552                 framenum = 0;
    5553 
    5554             rewindtime = framesPlayed - framenum;
     5897            rewindtime = seekcount;
    55555898            while (rewindtime > 0)
    55565899                usleep(1000);
    55575900        }
     
    55825925    UpdateEditSlider();
    55835926}
    55845927
     5928int NuppelVideoPlayer::GetCutStatus(long long testframe) const
     5929{
     5930    int retval = 0;
     5931    QMap<long long, int>::const_iterator i;
     5932    i = deleteMap.find(testframe);
     5933    if (i == deleteMap.end()) {
     5934        // testframe is not an explicit cutpoint
     5935        // See if it is in a deleted area
     5936        if (IsInDelete(testframe))
     5937            retval = 1;
     5938    } else {
     5939        int direction = *i;
     5940        if (direction == 0)
     5941            retval = 2;
     5942        else
     5943            retval = 3;
     5944    }
     5945
     5946    return retval;
     5947}
     5948
    55855949bool NuppelVideoPlayer::IsInDelete(long long testframe) const
    55865950{
    55875951    long long startpos = 0;
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/NuppelVideoPlayer.h myth.20155.0309b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
     
    101101    kDisplayTeletextMenu        = 0x40,
    102102};
    103103
     104class DeletePointInfo
     105{
     106    public:
     107        DeletePointInfo() :
     108            deleteframe(0), deletepoint(false), cut_after(false), direction(0) {}
     109
     110        long long deleteframe;
     111        bool deletepoint;
     112        bool cut_after;
     113        int direction;
     114};
     115
     116
    104117class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
    105118{
    106119    friend class PlayerContext;
     120    friend class GridEditCutpoints;
     121    friend class TV;
    107122
    108123  public:
    109124    NuppelVideoPlayer();
     
    282297    bool EnableEdit(void);
    283298    bool DoKeypress(QKeyEvent *e);
    284299    bool GetEditMode(void) const { return editmode; }
     300    bool GetHideEdits(void) const { return hideedits; }
    285301
    286302    // Decoder stuff..
    287303    VideoFrame *GetNextVideoFrame(bool allow_unsafe = true);
     
    301317    void ShutdownYUVResize(void);
    302318    void SaveScreenshot(void);
    303319
     320    // Edit stuff
     321    bool EditSeekToFrame(long long targetFrame);
     322    void SetScreenGrabSizes(QSize normal, QSize small);
     323    bool GetScreenGrabsOfCurrentFrame(QImage & normal, QImage &small); // Get current frame
     324
     325
     326    void       EditHandleClearMap();
     327    void       EditHandleInvertMap();
     328    void       EditHandleLoadCommSkip();
     329
     330    void ShowEditRecordingGrid();
     331
    304332    // Reinit
    305333    void    ReinitOSD(void);
    306334    void    ReinitVideo(void);
     
    420448    bool PosMapFromEnc(unsigned long long          start,
    421449                       QMap<long long, long long> &posMap);
    422450
     451    // Stuf for GridEditCutpoints
     452    long long CalcCutPointSeek(long long baseframe, bool right);
     453    // returns
     454    // 0 - no cut
     455    // 1 - is deleted
     456    // 2 - cut left
     457    // 3 - cut right
     458    int  GetCutStatus(long long testframe) const;
     459    long long GetSeekAmount() { return seekamount; }
     460    QString GetSeekAmountText() { return seekamounttext; }
     461
    423462  protected:
    424463    void DisplayPauseFrame(void);
    425464    void DisplayNormalFrame(void);
     
    502541    void HandleSelect(bool allowSelectNear = false);
    503542    void HandleResponse(void);
    504543
     544    DeletePointInfo GetDeletePointInfo(long long frame, bool allowSelectNear);
     545
     546    void SetupScreenGrab();
     547    void ClearScreenGrab();
     548
    505549    void UpdateTimeDisplay(void);
     550    int  GetSeekAmountPos() { return seekamountpos; }
    506551    void UpdateSeekAmount(bool up);
     552    void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; }
     553    void UpdateSeekAmountDisplay(void);
    507554    void UpdateEditSlider(void);
    508555
    509556    // Private A/V Sync Stuff
     
    576623    bool     livetv;
    577624    bool     watchingrecording;
    578625    bool     editmode;
     626    bool     hideedits;
    579627    bool     resetvideo;
    580628    bool     using_null_videoout;
    581629    bool     no_audio_in;
     
    596644    long long fftime;
    597645    /// 1..9 == keyframe..10 minutes. 0 == cut point
    598646    int       seekamountpos;
     647    ///  Used for Grid Edit logic
     648    bool      allow_pagesize;
     649    int       half_page;
    599650    /// Seekable frame increment when not using exact seeks.
    600651    /// Usually equal to keyframedist.
    601652    int      seekamount;
     653    QString  seekamounttext; // OSD seek units
    602654    /// Iff true we ignore seek amount and try to seek to an
    603655    /// exact frame ignoring key frame restrictions.
    604656    bool     exactseeks;
     
    737789    QMutex              yuv_lock;
    738790    QWaitCondition      yuv_wait;
    739791
     792    // EditGrid still image capture
     793    ImgReSampleContext *grid_edit_image_scaler;
     794    ImgReSampleContext *grid_edit_image_small_scaler;
     795    unsigned char      *grid_edit_image_buffer_yuv;
     796    unsigned char      *grid_edit_image_small_buffer_yuv;
     797    unsigned char      *grid_edit_image_buffer_rgb;
     798    unsigned char      *grid_edit_image_small_buffer_rgb;
     799    int                 grid_edit_image_buffer_length;
     800    int                 grid_edit_image_small_buffer_length;
     801    QSize               grid_edit_image_in_size;
     802    QSize               grid_edit_image_size;
     803    QSize               grid_edit_image_small_size;
     804
    740805    // Filters
    741806    QMutex   videofiltersLock;
    742807    QString  videoFiltersForProgram;
  • mythtv/libs/libmythtv/grideditcutpoints.cpp

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/grideditcutpoints.cpp myth.20155.0309b/mythtv/libs/libmythtv/grideditcutpoints.cpp
     
     1#include <math.h>
     2#include <unistd.h>
     3#include <iostream>
     4#include <algorithm>
     5using namespace std;
     6
     7#include <QApplication>
     8#include <QPainter>
     9#include <QFont>
     10#include <QKeyEvent>
     11#include <QEvent>
     12#include <QPixmap>
     13#include <QPaintEvent>
     14#include <QCursor>
     15#include <QImage>
     16#include <QLayout>
     17#include <QLabel>
     18#include <QDateTime>
     19#include <QRect>
     20
     21#include "mythcontext.h"
     22#include "mythdbcon.h"
     23#include "grideditcutpoints.h"
     24#include "grideditimages.h"
     25#include "NuppelVideoPlayer.h"
     26
     27void GridEditCutpoints::Run(NuppelVideoPlayer *player)
     28{
     29    VERBOSE(VB_GENERAL, "Starting");
     30    gContext->addCurrentLocation("GridEditCutpoints");
     31
     32    GridEditCutpoints *er = new GridEditCutpoints(gContext->GetMainWindow(),
     33                                  player, "editrecording");
     34
     35    if (er->isValid())
     36    {
     37        er->Show();
     38        er->displayInitialFrame();
     39        er->exec();
     40    }
     41
     42    delete er;
     43
     44    gContext->removeCurrentLocation();
     45    VERBOSE(VB_GENERAL, "Ending");
     46}
     47
     48GridEditCutpoints::GridEditCutpoints(MythMainWindow *parent,
     49                     NuppelVideoPlayer *player, const char *name)
     50         : MythThemedDialog(parent, "grideditcutpoints", "", name)
     51{
     52    m_player = player;
     53    m_images = new GridEditImages(this, player);
     54
     55    int i;
     56    m_gridimagemain = NULL;
     57    for (i = m_gridimages.minIndex(); i < m_gridimages.maxIndex(); i++)
     58    {
     59        m_gridimages[i] = NULL;
     60    }
     61
     62    usedSubVideoCount=0;
     63
     64    QSize videoSizeMain, videoSizeSmall;
     65
     66    m_gridimagemain = getUIGridEditImageType("mainvideo");
     67    if (m_gridimagemain)
     68        videoSizeMain = m_gridimagemain->getScreenArea().size();
     69    else
     70    {
     71        VERBOSE(VB_IMPORTANT, "FATAL: Couldn't find mainedit:mainvideo");
     72        return;
     73    }
     74
     75    // Small version of main frame
     76    m_gridimages[0] = getUIGridEditImageType("video0");
     77
     78    for (i = 1; i < m_gridimages.maxIndex(); i++)
     79    {
     80        QString p = QString("videop%1").arg(i);
     81        QString m = QString("videom%1").arg(i);
     82
     83        // Minus frame i
     84        m_gridimages[-i] = getUIGridEditImageType(m);
     85        if (m_gridimages[-i])
     86        {
     87            QSize tmpVideoSizeSmall = m_gridimages[-i]->getScreenArea().size();
     88            if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall)
     89                VERBOSE(VB_IMPORTANT,
     90                        QString("Multiple sizes found for edit videos (%1)").arg(m));
     91            else
     92                videoSizeSmall = tmpVideoSizeSmall;
     93            if (i > usedSubVideoCount) usedSubVideoCount=i;
     94        }
     95
     96        m_gridimages[i] = getUIGridEditImageType(p);
     97        if (m_gridimages[i])
     98        {
     99            QSize tmpVideoSizeSmall = m_gridimages[i]->getScreenArea().size();
     100            if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall)
     101                VERBOSE(VB_IMPORTANT,
     102                        QString("Multiple sizes found for edit videos (%1)").arg(p));
     103            else
     104                videoSizeSmall = tmpVideoSizeSmall;
     105            if (i > usedSubVideoCount) usedSubVideoCount=i;
     106        }
     107    }
     108
     109    imageScreenArea = m_gridimages[-usedSubVideoCount]->getOuterBorder();
     110    for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++)
     111        if (m_gridimages[i])
     112            imageScreenArea = imageScreenArea.unite(m_gridimages[i]->getOuterBorder());
     113
     114    m_images->SetVideoInfo(usedSubVideoCount, videoSizeMain, videoSizeSmall);
     115
     116    m_player->SetHalfPageSize(usedSubVideoCount);
     117    m_slider = getUIGridEditSliderType("positionbar");
     118    if (!m_slider)
     119        VERBOSE(VB_GENERAL, "Missing positionbar for GridEditCutpoints");
     120
     121    // Get Status boxes
     122    {
     123        m_framenum    = getUITextType("framenum");
     124        m_time        = getUITextType("time");
     125        m_cutind      = getUITextType("cutind");
     126        m_jumpstyle   = getUITextType("jumpstyle");
     127        m_updatingind = getUITextType("updatingind");
     128    }
     129
     130    VERBOSE(VB_GENERAL, QString("main = (%1, %2) small = (%3, %4)")
     131                       .arg(videoSizeMain.width()).arg(videoSizeMain.height())
     132                       .arg(videoSizeSmall.width()).arg(videoSizeSmall.height()));
     133
     134    slowMotionDirection = 1; // start off play forward
     135    slowMotionActive = false;
     136    readyForNextFrame = false;
     137    slowMotionTimer = new QTimer(this);
     138    QObject::connect(slowMotionTimer, SIGNAL(timeout()),
     139                     this,           SLOT(updateSlowMotion()));
     140
     141    movingCutpoint = false;
     142    // Create blank pixmaps...
     143 
     144    updateBackground();
     145
     146    updateStats();
     147
     148    setNoErase();
     149    gContext->addListener(this);
     150   
     151    updateForeground();
     152}
     153
     154GridEditCutpoints::~GridEditCutpoints()
     155{
     156    if (m_images)
     157    {
     158        delete m_images;
     159        m_images = NULL;
     160    }
     161    gContext->removeListener(this);
     162}
     163
     164void GridEditCutpoints::displayInitialFrame()
     165{
     166    refreshImages();
     167    refreshCutList();
     168    updateStats();
     169    SetUpdating(false);
     170}
     171
     172void GridEditCutpoints::updateSlowMotion()
     173{
     174    if (!slowMotionActive)
     175        slowMotionTimer->stop();
     176    else if (readyForNextFrame && slowMotionDirection != 0)
     177    {
     178        readyForNextFrame=false;
     179
     180        if (slowMotionDirection > 0)
     181            EditHandleRight();
     182        else if (slowMotionDirection < 0)
     183            EditHandleLeft();
     184    }
     185}
     186
     187
     188void GridEditCutpoints::setSlowMotionSpeed()
     189{
     190    // slowMotionDirection is max FPS
     191
     192    if (slowMotionDirection != 0)
     193    {
     194        int smd = slowMotionDirection;
     195        if (smd < 0) smd = -smd;
     196        int timeout = 1000 / smd;
     197
     198        slowMotionTimer->start(timeout);
     199    }
     200    SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection));
     201}
     202
     203
     204void GridEditCutpoints::keyPressEvent(QKeyEvent *e)
     205{
     206    // keyDown limits keyrepeats to prevent continued scrolling
     207    // after key is released. Note: Qt's keycompress should handle
     208    // this but will fail with fast key strokes and keyboard repeat
     209    // enabled. Keys will not be marked as autorepeat and flood buffer.
     210    // setFocusPolicy(QWidget::ClickFocus) in constructor is important
     211    // or keyRelease events will not be received after a refocus.
     212   
     213    bool handled = false;
     214
     215    QStringList actions;
     216    gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions);
     217
     218    {
     219        for (unsigned int i = 0; i < actions.size() && !handled; i++)
     220        {
     221            QString action = actions[i];
     222            handled = true;
     223
     224            if (action == "SELECT")
     225            {
     226                if (slowMotionActive)
     227                {
     228                    slowMotionActive = false;
     229                    slowMotionTimer->stop();
     230                }
     231                else if (movingCutpoint)
     232                {
     233                    // Move cutpoint
     234                    m_player->DeleteMark(savedCutpoint);
     235                    m_player->AddMark(m_images->GetCurrentFrameNumber(), savedCutType);
     236                    movingCutpoint = false;
     237                    refreshCutList();
     238                    refreshImages();
     239                }
     240                else
     241                    handleSelect();
     242            }
     243            else if (action == "PAUSE")
     244            {
     245                if (movingCutpoint)
     246                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     247                                              "Moving Cutpoint",
     248                                              "Slow Motion Unavailable when moving cutpoint");
     249                else if (slowMotionActive)
     250                {
     251                    slowMotionActive = false;
     252                    slowMotionTimer->stop();
     253                }
     254            }
     255            else if (action == "SLOWMO")
     256            {
     257                if (movingCutpoint)
     258                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     259                                              "Moving Cutpoint",
     260                                              "Slow Motion Unavailable when moving cutpoint");
     261                else
     262                {
     263                    if (slowMotionActive)
     264                    {
     265                        slowMotionActive = false;
     266                        slowMotionTimer->stop();
     267                    }
     268                    else
     269                    {
     270                        slowMotionActive = true;
     271                        readyForNextFrame = true;
     272                        slowMotionDirection = 1;
     273
     274                        // force to either 1 frame. 1/2 page or full page motion
     275                        int i;
     276                        // move to 1 frame if on cutpoint
     277                        for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++)
     278                            m_player->UpdateSeekAmount(true);
     279
     280                        // move to fullpage if higher
     281                        for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++)
     282                            m_player->UpdateSeekAmount(false);
     283
     284                        setSlowMotionSpeed();
     285                    }
     286                }
     287            }
     288            else if (action == "LEFT")
     289            {
     290                if (slowMotionActive)
     291                {
     292                    slowMotionDirection--;
     293                    setSlowMotionSpeed();
     294                }
     295                else
     296                {
     297                    SetUpdating(true);
     298                    EditHandleLeft();
     299                }
     300            }
     301            else if (action == "RIGHT" )
     302            {
     303                if (slowMotionActive)
     304                {
     305                    slowMotionDirection++;
     306                    setSlowMotionSpeed();
     307                }
     308                else
     309                {
     310                    SetUpdating(true);
     311                    EditHandleRight();
     312                }
     313            }
     314            else if (action == "UP")
     315            {
     316                m_player->UpdateSeekAmount(true);
     317                updateStats();
     318            }
     319            else if (action == "DOWN")
     320            {
     321                if ((movingCutpoint || slowMotionActive) && m_player->GetSeekAmountPos() == 2)
     322                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     323                                              "Moving Cutpoint",
     324                                              "CutPoint skip Unavailable");
     325                else
     326                {
     327                    m_player->UpdateSeekAmount(false);
     328                    updateStats();
     329                }
     330            }
     331            else if (action == "CLEARMAP")
     332            {
     333                if (movingCutpoint || slowMotionActive)
     334                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     335                                              "Moving Cutpoint",
     336                                              "Clear Cut Map Unavailable");
     337                else
     338                {
     339                    SetUpdating(true);
     340                    m_player->EditHandleClearMap();
     341                    refreshCutList();
     342                    updateStats();
     343                }
     344            }
     345            else if (action == "INVERTMAP")
     346            {
     347                if (movingCutpoint || slowMotionActive)
     348                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     349                                              "Moving Cutpoint",
     350                                              "Invert Cut Map Unavailable");
     351                else
     352                {
     353                    SetUpdating(true);
     354                    m_player->EditHandleInvertMap();
     355                    refreshCutList();
     356                    updateStats();
     357                }
     358            }
     359            else if (action == "LOADCOMMSKIP")
     360            {
     361                if (movingCutpoint || slowMotionActive)
     362                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     363                                              "Moving Cutpoint",
     364                                              "Load Comm Skip Map Unavailable");
     365                else
     366                {
     367                    SetUpdating(true);
     368                    m_player->EditHandleLoadCommSkip();
     369                    refreshCutList();
     370                    updateStats();
     371                }
     372            }
     373            else if (action == "PREVCUT")
     374            {
     375                if (movingCutpoint || slowMotionActive)
     376                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     377                                              "Moving Cutpoint",
     378                                              "Prev Cut Unavailable");
     379                else
     380                {
     381                    SetUpdating(true);
     382                    EditHandlePrevCut();
     383                }
     384            }
     385            else if (action == "NEXTCUT")
     386            {
     387                if (movingCutpoint || slowMotionActive)
     388                    MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     389                                              "Moving Cutpoint",
     390                                              "Next Cut Unavailable");
     391                else
     392                {
     393                    SetUpdating(true);
     394                    EditHandleNextCut();
     395                }
     396            }
     397            else if (action == "BIGJUMPREW")
     398            {
     399                SetUpdating(true);
     400                EditHandleBigJumpRew();
     401            }
     402            else if (action == "BIGJUMPFWD")
     403            {
     404                SetUpdating(true);
     405                EditHandleBigJumpFwd();
     406            }
     407            else if (action == "ESCAPE" && movingCutpoint)
     408                movingCutpoint = false;
     409            else if (action == "ESCAPE" || action == "TOGGLEEDIT" ||
     410                     action == "MENU")
     411                escape();
     412            else
     413                handled = false;
     414
     415            if (movingCutpoint)
     416                SetUpdating(true, "Moving Cutpoint");
     417            else if (!slowMotionActive)
     418                SetUpdating(false);
     419        }
     420    }
     421
     422    if (!handled)
     423        MythDialog::keyPressEvent(e);
     424}
     425
     426void GridEditCutpoints::EditHandleLeft(int seektype)
     427{
     428    long long seekamount = m_player->GetSeekAmount();
     429    bool cutpointseek = false;
     430
     431    if (seektype == -2 || seekamount == -2)
     432        cutpointseek = true;
     433    else
     434    {
     435        // seektype == 1 for normal, 10 for bigjump
     436        seekamount *= seektype;
     437    }
     438
     439    if (seekamount < 0) // Invalid -- keyframe
     440        seekamount = 1;
     441
     442    m_images->SeekLeft(seekamount, cutpointseek);
     443
     444    refreshImages();
     445    updateStats();
     446}
     447
     448void GridEditCutpoints::EditHandleRight(int seektype)
     449{
     450    long long seekamount = m_player->GetSeekAmount();
     451    bool cutpointseek=false;
     452
     453    if (seektype == -2 || seekamount == -2)
     454        cutpointseek = true;
     455    else
     456    {
     457        // seektype == 1 for normal, 10 for bigjump
     458        seekamount *= seektype;
     459    }
     460
     461    if (seekamount < 0) // Invalid -- keyframe
     462        seekamount = 1;
     463
     464    m_images->SeekRight(seekamount, cutpointseek);
     465
     466    refreshImages();
     467     updateStats();
     468}
     469
     470void GridEditCutpoints::handleSelect(void)
     471{
     472    bool needupdate = false;
     473    // add / update cutpoint
     474    // -or-
     475    // delete / flip / move cutpoint
     476
     477    // if no cut points on screen
     478    //    "Delete Before"
     479    //    "Delete After"
     480
     481    // if on existing cutpoint
     482    //    "Delete cutpoint"
     483    //    "Flip directions"
     484
     485    // FIXME
     486    // if a cutpoint exists on the screen but not on the current frame
     487    //    "Move to current frame"
     488    //    "Add new"
     489
     490    FrameStats fs = m_images->GetMainFrameStats();
     491    DeletePointInfo dpi = m_player->GetDeletePointInfo(fs.frameNumber, true);
     492
     493    if (fs.cutInd >= 2)
     494    {
     495        QString title = "";
     496        QString message = "Cutpoint exists:";
     497        QStringList buttons;
     498        buttons.append("Delete cutpoint?");
     499        buttons.append("Move cutpoint?");
     500        if (fs.cutInd == 2)
     501            buttons.append("Flip directions (Cut After)?");
     502        else
     503            buttons.append("Flip directions (Cut Before)?");
     504
     505        DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
     506                                                      title, message, buttons, kDialogCodeButton0);
     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());
     567    repaint(imageScreenArea);
     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;
     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 myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/grideditcutpoints.h myth.20155.0309b/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
     74    long long savedCutpoint;
     75    int       savedCutType;
     76    bool      movingCutpoint;
     77
     78    UITextType   *m_framenum;
     79    UITextType   *m_time;
     80    UITextType   *m_cutind;
     81    UITextType   *m_jumpstyle;
     82    UITextType   *m_updatingind;
     83 
     84    UIGridEditSliderType  *m_slider;
     85    QTimer                *slowMotionTimer;
     86    int                    slowMotionDirection;
     87    bool                   slowMotionActive;
     88    bool                   readyForNextFrame;
     89
     90    QRect                  imageScreenArea;
     91};
     92
     93#endif
  • mythtv/libs/libmythtv/grideditimages.cpp

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

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/grideditimages.h myth.20155.0309b/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,
     48                            myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages);
     49
     50        // return true if anything changed
     51        bool refreshImages(UIGridEditImageType* gridimagemain,
     52                           myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages,
     53                           bool mainFrameOnly);
     54
     55        void SeekLeft(long long seekamount, bool cutpointseek = false);
     56        void SeekRight(long long seekamount, bool cutpointseek = false);
     57
     58        FrameStats GetMainFrameStats();
     59        long long GetCurrentFrameNumber() const { return stillMainFrameNumber; }
     60        long long GetMaxFrameNumber() const { return maxFrameNumber; }
     61
     62        void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall);
     63
     64    protected slots:
     65        void updateAllFrames();
     66
     67    private:
     68        // Private functions
     69        void clearStillFrames();
     70        void printStillFrameStats(QString caption);
     71        void checkMaxFrameCount();
     72
     73        // 'newlevel' paramter for getStillFrames():
     74        //  0 = get on screen Frames only
     75        //  1 = get preCache Frames only
     76        //  2 = get any necessary frames
     77        //  3 = done
     78        bool getFrameIndexes(int newlevel);
     79
     80        bool getStillFrames(int maxcount = 1000);
     81        void getMainStillFrame();
     82        bool getSpecificFrame(long long frameindex);
     83        void getFrame(long long i, int &cutFrame, QPixmap* &stillFrame, QPixmap* &stillFrameBig);
     84        void emptyCache();
     85
     86        // return true if anything changed
     87        bool shiftStillFramesLeft(long long offset);
     88        bool shiftStillFramesRight(long long offset);
     89        void startFrameCaching();
     90        void stopFrameCaching() { getImagesTimer->stop(); };
     91
     92        QPixmap *makeScaledPixmap(const QImage& qim, QSize sz);
     93
     94        void SetPreCache(long long pccount);
     95
     96        // Private data
     97        // These frames are in the cutlist
     98        // 0 == not cut
     99        // 1 == cut
     100        // 2 == cutpoint (cut left)
     101        // 3 == cutpoint (cut right)
     102        myArray<int, MAX_SUB_VIDEOS> cutFrames;
     103        myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames;
     104        myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig;
     105
     106        // pre-caching large seek amounts
     107        // (i.e. while seeking +5 seconds, these are places to store the to-be-displayed data)
     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 myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/libmythtv.pro myth.20155.0309b/mythtv/libs/libmythtv/libmythtv.pro
     
    363363    # Misc. frontend
    364364    HEADERS += guidegrid.h              infostructs.h
    365365    HEADERS += ttfont.h
     366    HEADERS += grideditcutpoints.h      grideditimages.h
    366367    SOURCES += guidegrid.cpp            infostructs.cpp
    367368    SOURCES += ttfont.cpp
     369    SOURCES += grideditcutpoints.cpp    grideditimages.cpp
    368370
    369371    using_mheg {
    370372        # DSMCC stuff
  • mythtv/libs/libmythtv/tv_play.cpp

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/tv_play.cpp myth.20155.0309b/mythtv/libs/libmythtv/tv_play.cpp
     
    2828#include "remoteencoder.h"
    2929#include "remoteutil.h"
    3030#include "guidegrid.h"
     31#include "grideditcutpoints.h"
    3132//#include "progfind.h"
    3233#include "NuppelVideoPlayer.h"
    3334#include "programinfo.h"
     
    573574    REG_KEY("TV Editing", "BIGJUMPFWD", "Jump forward 10x the normal amount",
    574575            ">,.");
    575576    REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E");
     577    REG_KEY("TV Editing", "SLOWMO", "Slow Motion Play", "Ctrl+P");
     578    REG_KEY("TV Editing", "PAUSE", "Pause", "P");
    576579
    577580    /* Teletext keys */
    578581    REG_KEY("Teletext Menu", "NEXTPAGE",    "Next Page",             "Down");
     
    32323235    if (editmode)
    32333236    {
    32343237        actx->LockDeleteNVP(__FILE__, __LINE__);
     3238        if (actx->nvp && actx->nvp->GetHideEdits())
     3239        {
     3240            actx->UnlockDeleteNVP(__FILE__, __LINE__);
     3241            return;
     3242        }
    32353243        if (actx->nvp && !actx->nvp->DoKeypress(e))
    32363244            editmode = actx->nvp->GetEditMode();
    32373245        actx->UnlockDeleteNVP(__FILE__, __LINE__);
     
    76997707    qApp->postEvent(myWindow, me);
    77007708}
    77017709
     7710void TV::ShowEditRecordingGrid()
     7711{
     7712     // post the request to the main UI thread
     7713     // it will be caught in eventFilter and processed as CustomEvent
     7714     // this will create the program guide window (widget)
     7715     // on the main thread and avoid a deadlock on Win32
     7716
     7717     VERBOSE(VB_GENERAL, "Starting Grid Edit");
     7718     QString message = QString("START_EDIT");
     7719     MythEvent* me = new MythEvent(message);
     7720     qApp->postEvent(myWindow, me);
     7721}
     7722
    77027723void TV::ChangeVolume(PlayerContext *ctx, bool up)
    77037724{
    77047725    ctx->LockDeleteNVP(__FILE__, __LINE__);
     
    83468367        DoEditSchedule(editType);
    83478368    }
    83488369
     8370    if (message.left(10) == "START_EDIT")
     8371    {
     8372        const PlayerContext *mctx =
     8373            GetPlayerReadLock(0, __FILE__, __LINE__);
     8374        mctx->LockDeleteNVP(__FILE__, __LINE__);
     8375        if (mctx->nvp)
     8376            mctx->nvp->ShowEditRecordingGrid();
     8377
     8378        mctx->UnlockDeleteNVP(__FILE__, __LINE__);
     8379        ReturnPlayerLock(mctx);
     8380    }
     8381
    83498382    if (message.left(14) == "COMMFLAG_START")
    83508383    {
    83518384        QString evchanid = QString::null;
  • mythtv/libs/libmythtv/tv_play.h

    diff -r -u -N -X diff.exclude.noxml -x myth.20155.0309a -x myth.20155.0309b myth.20155.0309a/mythtv/libs/libmythtv/tv_play.h myth.20155.0309b/mythtv/libs/libmythtv/tv_play.h
     
    199199    void setInPlayList(bool setting) { inPlaylist = setting; }
    200200    void setUnderNetworkControl(bool setting) { underNetworkControl = setting; }
    201201
     202    void ShowEditRecordingGrid();
    202203    void ShowNoRecorderDialog(const PlayerContext*,
    203204                              NoRecorderMsg msgType = kNoRecorders);
    204205    void FinishRecording(int player_idx); ///< Finishes player's recording