Ticket #6322: 137-editgrid.fixes.code.5.patch
| File 137-editgrid.fixes.code.5.patch, 104.8 KB (added by , 17 years ago) |
|---|
-
mythtv/libs/libmyth/mythdialogs.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/mythdialogs.cpp release.20115.0305gridedit/mythtv/libs/libmyth/mythdialogs.cpp
1258 1258 rect_to_update = this->geometry(); 1259 1259 } 1260 1260 1261 redrawRect = redrawRect.unite(r );1261 redrawRect = redrawRect.unite(rect_to_update); 1262 1262 1263 1263 update(redrawRect); 1264 1264 } … … 1600 1600 return GetUIType<UIBlackHoleType>(this, name); 1601 1601 } 1602 1602 1603 UIGridEditImageType* MythThemedDialog::getUIGridEditImageType(const QString &name) 1604 { 1605 return GetUIType<UIGridEditImageType>(this, name); 1606 } 1607 1608 UIGridEditSliderType* MythThemedDialog::getUIGridEditSliderType(const QString &name) 1609 { 1610 return GetUIType<UIGridEditSliderType>(this, name); 1611 } 1612 1603 1613 UIImageType* MythThemedDialog::getUIImageType(const QString &name) 1604 1614 { 1605 1615 return GetUIType<UIImageType>(this, name); -
mythtv/libs/libmyth/mythdialogs.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/mythdialogs.h release.20115.0305gridedit/mythtv/libs/libmyth/mythdialogs.h
33 33 class UICheckBoxType; 34 34 class UISelectorType; 35 35 class UIBlackHoleType; 36 class UIGridEditImageType; 37 class UIGridEditSliderType; 36 38 class UIImageType; 37 39 class UIImageGridType; 38 40 class UIStatusBarType; … … 373 375 UICheckBoxType *getUICheckBoxType(const QString &name); 374 376 UISelectorType *getUISelectorType(const QString &name); 375 377 UIBlackHoleType *getUIBlackHoleType(const QString &name); 378 UIGridEditImageType *getUIGridEditImageType(const QString &name); 379 UIGridEditSliderType *getUIGridEditSliderType(const QString &name); 376 380 UIImageGridType *getUIImageGridType(const QString &name); 377 381 UIImageType *getUIImageType(const QString &name); 378 382 UIStatusBarType *getUIStatusBarType(const QString &name); -
mythtv/libs/libmyth/uitypes.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/uitypes.cpp release.20115.0305gridedit/mythtv/libs/libmyth/uitypes.cpp
5338 5338 5339 5339 // ******************************************************************** 5340 5340 5341 UIGridEditImageType::UIGridEditImageType(const QString &name) 5342 : UIType(name) 5343 { 5344 cutStatus = 0; 5345 highlightFrame = false; // Used to highlight frame #0 5346 framenumber = -1; 5347 } 5348 5349 void UIGridEditImageType::calculateScreenArea() 5350 { 5351 QRect r = area; 5352 r.moveBy(m_parent->GetAreaRect().left(), 5353 m_parent->GetAreaRect().top()); 5354 screen_area = r; 5355 5356 inner_border.setLeft(screen_area.left()+1); 5357 inner_border.setRight(screen_area.right()-1); 5358 inner_border.setTop(screen_area.top()+1); 5359 inner_border.setBottom(screen_area.bottom()-1); 5360 5361 outer_border = screen_area; 5362 } 5363 5364 void UIGridEditImageType::Draw(QPainter *p, int drawlayer, int context) 5365 { 5366 if (pmap.isNull()) 5367 { 5368 QColor drawcolor = QColor( 0, 0, 0); 5369 p->setBrush(QBrush(Qt::SolidPattern)); 5370 p->setPen(QPen(drawcolor, 2)); 5371 p->drawRect(screen_area); 5372 } 5373 else 5374 { 5375 p->drawPixmap(screen_area, pmap); 5376 5377 p->setBrush(QBrush(Qt::NoBrush)); 5378 // Draw the frame outline 5379 // This may be covered by the cut indicator 5380 // Or the highlight 5381 5382 p->setPen(QPen(colorSet[0], 3)); 5383 p->drawRect(outer_border); 5384 5385 if (cutStatus > 0) 5386 { 5387 p->setPen(QPen(colorSet[cutStatus], 3)); 5388 p->drawRect(inner_border); 5389 p->drawLine(inner_border.topLeft(), inner_border.bottomRight()); 5390 p->drawLine(inner_border.bottomLeft(), inner_border.topRight()); 5391 } 5392 if (highlightFrame) 5393 { 5394 // Overlay the image frame with the standard frame color 5395 // This is used to highlight small frame #0 5396 p->setPen(QPen(highlightColor, 3)); 5397 p->drawRect(outer_border); 5398 } 5399 } 5400 } 5401 5402 void UIGridEditImageType::setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus) 5403 { 5404 // We can get a null new_pmap at the start or end of the video 5405 if (! new_pmap) 5406 { 5407 clearPixmap(); 5408 return; 5409 } 5410 5411 if (frame == framenumber) 5412 { 5413 // No change in pixmap (?) 5414 setCutStatus(new_cutStatus); 5415 return; 5416 } 5417 5418 pmap = *new_pmap; 5419 framenumber = frame; 5420 5421 if (new_cutStatus >= 0 && new_cutStatus <= 3) 5422 cutStatus = new_cutStatus; 5423 else 5424 cutStatus = 0; 5425 5426 refresh(); 5427 } 5428 5429 void UIGridEditImageType::clearPixmap(bool dorefresh) 5430 { 5431 if (! pmap.isNull()) 5432 { 5433 pmap = QPixmap(); 5434 5435 cutStatus = 0; 5436 framenumber = -1; 5437 if (dorefresh) 5438 refresh(); 5439 } 5440 } 5441 5442 void UIGridEditImageType::setCutStatus(int new_cutStatus) 5443 { 5444 if (new_cutStatus == cutStatus) 5445 return; 5446 5447 if (new_cutStatus >= 0 && new_cutStatus <= 3) 5448 cutStatus = new_cutStatus; 5449 else 5450 cutStatus = 0; 5451 5452 refresh(); 5453 } 5454 5455 // ******************************************************************** 5456 5457 UIGridEditSliderType::UIGridEditSliderType(const QString &name) 5458 : UIType(name) 5459 { 5460 m_drawMap = NULL; 5461 m_position=0; 5462 } 5463 5464 void UIGridEditSliderType::calculateScreenArea() 5465 { 5466 QRect r = area; 5467 r.moveBy(m_parent->GetAreaRect().left(), 5468 m_parent->GetAreaRect().top()); 5469 screen_area = r; 5470 5471 if (m_drawMap) 5472 delete [] m_drawMap; 5473 5474 m_drawWidth = area.width(); 5475 m_drawMap = new unsigned char[m_drawWidth]; 5476 for (int i = 0; i < m_drawWidth; i++) 5477 m_drawMap[i] = 0; 5478 } 5479 5480 void UIGridEditSliderType::ClearAll() 5481 { 5482 for (int i = 0; i < m_drawWidth; i++) 5483 m_drawMap[i] = 0; 5484 refresh(); 5485 } 5486 5487 void UIGridEditSliderType::SetRange( 5488 long long fstart, long long fend, long long fcount) 5489 { 5490 if (fcount <= 0) 5491 { 5492 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 5493 .arg(fcount)); 5494 return; 5495 } 5496 if (fstart < 0) 5497 { 5498 VERBOSE(VB_IMPORTANT, QString("Invalid starting frame: %1") 5499 .arg(fstart)); 5500 return; 5501 } 5502 if (fend < 0) 5503 { 5504 VERBOSE(VB_IMPORTANT, QString("Invalid ending frame: %1") 5505 .arg(fend)); 5506 return; 5507 } 5508 5509 if (fstart > fcount) fstart = fcount; 5510 if (fend > fcount) fend = fcount; 5511 5512 int start = (int)((1.0 * fstart * m_drawWidth) / fcount); 5513 int end = (int)((1.0 * fend * m_drawWidth) / fcount); 5514 5515 if (start < 0) 5516 start = 0; 5517 if (start >= m_drawWidth) 5518 start = m_drawWidth - 1; 5519 if (end < 0) 5520 end = 0; 5521 if (end >= m_drawWidth) 5522 end = m_drawWidth - 1; 5523 5524 if (end < start) 5525 { 5526 int tmp = start; 5527 start = end; 5528 end = tmp; 5529 } 5530 5531 for (int i = start; i < end; i++) 5532 if (m_drawMap[i] < 1) 5533 m_drawMap[i] = 1; 5534 5535 // Mark endpoints 5536 m_drawMap[start] = 2; 5537 m_drawMap[end] = 2; 5538 5539 VERBOSE(VB_GENERAL, QString("Range = %1 - %2 (%3 - %4)") 5540 .arg(start).arg(end) 5541 .arg(fstart).arg(fend)); 5542 refresh(); 5543 } 5544 5545 void UIGridEditSliderType::SetPosition( 5546 long long fposition, long long fcount) 5547 { 5548 if (fcount <= 0) 5549 { 5550 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 5551 .arg(fcount)); 5552 return; 5553 } 5554 5555 if (fposition < 0) 5556 { 5557 VERBOSE(VB_IMPORTANT, QString("Invalid position frame: %1") 5558 .arg(fposition)); 5559 return; 5560 } 5561 5562 if (fposition > fcount) fposition = fcount; 5563 5564 int new_position = (int)(1.0 * fposition * m_drawWidth) / fcount; 5565 5566 if (new_position < 0) 5567 new_position = 0; 5568 if (new_position >= m_drawWidth) 5569 new_position = m_drawWidth - 1; 5570 5571 if (new_position != m_position) 5572 { 5573 m_position = new_position; 5574 refresh(); 5575 } 5576 } 5577 5578 void UIGridEditSliderType::Draw(QPainter *p, int drawlayer, int context) 5579 { 5580 // Draw Background 5581 p->setPen(QPen(colorSet[0], 2)); 5582 p->setBrush(colorSet[0]); 5583 p->drawRect(screen_area); 5584 5585 // Draw bars 5586 5587 // VERBOSE(VB_GENERAL, QString("Starting")); 5588 int i = 0; 5589 do { 5590 int start = 0; 5591 int end = 0; 5592 5593 while (i < m_drawWidth && m_drawMap[i] == 0) i++; 5594 if (i == m_drawWidth) break; 5595 start = i; 5596 5597 i++; 5598 5599 5600 while (i < m_drawWidth && m_drawMap[i] == 1) i++; 5601 end = i; 5602 if (end == m_drawWidth) end--; 5603 5604 // If the next map value is not a normal internal cutpoint 5605 // increment i so we handle it properly 5606 if (end+1 < m_drawWidth && m_drawMap[end+1] != 1) 5607 i++; 5608 5609 // start == starting point 5610 // end == endingpoint 5611 { 5612 QRect r = screen_area; 5613 r.setLeft(r.left() + start); 5614 r.setWidth(end - start); 5615 5616 // VERBOSE(VB_GENERAL, QString("Cut from (%1, %2) - (%3, %4)") 5617 // .arg(r.left()).arg(r.top()) 5618 // .arg(r.right()).arg(r.bottom())); 5619 5620 // VERBOSE(VB_GENERAL, QString("start = %1, m_position = %2, end = %3") 5621 // .arg(start) 5622 // .arg(m_position) 5623 // .arg(end)); 5624 5625 if (start <= m_position && m_position <= end) 5626 { 5627 p->setPen(QPen(colorSet[4], 2)); 5628 p->setBrush(colorSet[4]); 5629 } 5630 else 5631 { 5632 p->setPen(QPen(colorSet[1], 2)); 5633 p->setBrush(colorSet[1]); 5634 } 5635 p->drawRect(r); 5636 5637 p->setPen(QPen(colorSet[2], 2)); 5638 p->setBrush(colorSet[2]); 5639 if (m_drawMap[start] == 2) 5640 p->drawLine(r.topLeft(), r.bottomLeft()); 5641 if (m_drawMap[end] == 2) 5642 p->drawLine(r.topRight(), r.bottomRight()); 5643 5644 } 5645 } while (i < m_drawWidth); 5646 5647 // Draw Current Position Mark 5648 5649 QPoint ptop(screen_area.left() + m_position, screen_area.top()); 5650 QPoint pbot(screen_area.left() + m_position, screen_area.bottom()); 5651 5652 p->setPen(QPen(colorSet[3], 2)); 5653 p->setBrush(colorSet[3]); 5654 p->drawLine(ptop, pbot); 5655 } 5656 5657 // ******************************************************************** 5658 5341 5659 UIKeyType::UIKeyType(const QString &name) 5342 5660 : UIType(name) 5343 5661 { -
mythtv/libs/libmyth/uitypes.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/uitypes.h release.20115.0305gridedit/mythtv/libs/libmyth/uitypes.h
1385 1385 QRect area; 1386 1386 }; 1387 1387 1388 class MPUBLIC UIGridEditImageType : public UIType 1389 { 1390 Q_OBJECT 1391 1392 public: 1393 1394 UIGridEditImageType(const QString &name); 1395 void calculateScreenArea(); 1396 void setArea(QRect an_area) { area = an_area; }; 1397 1398 void setOutlineColor(QColor c) { colorSet[0] = c; }; 1399 void setCutColor(QColor c) { colorSet[1] = c; }; 1400 void setCutPointColor(QColor c) 1401 { 1402 colorSet[2] = c; // Cut before 1403 colorSet[3] = c; // Cut after 1404 }; 1405 void setHighlightFrame(bool high) { highlightFrame = high; }; 1406 void setHighlightColor(QColor c) { highlightColor = c; }; 1407 1408 virtual void Draw(QPainter *, int, int); 1409 void setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus); 1410 1411 void clearPixmap(bool dorefresh=true); 1412 void setCutStatus(int new_cutStatus); 1413 1414 QRect getOuterBorder() { return outer_border; }; 1415 protected: 1416 1417 QRect area; 1418 QRect inner_border; 1419 QRect outer_border; 1420 QPixmap pmap; 1421 long long framenumber; // for consistency checking 1422 int cutStatus; 1423 QColor colorSet[4]; 1424 bool highlightFrame; 1425 QColor highlightColor; 1426 }; 1427 1428 class MPUBLIC UIGridEditSliderType : public UIType 1429 { 1430 Q_OBJECT 1431 1432 public: 1433 1434 UIGridEditSliderType(const QString &name); 1435 void calculateScreenArea(); 1436 void setArea(QRect an_area) { area = an_area; }; 1437 1438 void setFillColor(QColor c) { colorSet[0] = c; }; 1439 void setCutColor(QColor c) { colorSet[1] = c; }; 1440 void setCutPointColor(QColor c) { colorSet[2] = c; }; 1441 void setPositionColor(QColor c) { colorSet[3] = c; }; 1442 void setInCutColor(QColor c) { colorSet[4] = c; }; 1443 1444 void ClearAll(); 1445 void SetRange(long long fstart, long long fend, long long fcount); 1446 void SetPosition(long long fposition, long long fcount); 1447 1448 virtual void Draw(QPainter *, int, int); 1449 protected: 1450 1451 QRect area; 1452 unsigned char *m_drawMap; 1453 int m_drawWidth; 1454 int m_position; 1455 1456 QColor colorSet[5]; 1457 }; 1458 1459 1388 1460 class MPUBLIC UIKeyType : public UIType 1389 1461 { 1390 1462 Q_OBJECT -
mythtv/libs/libmyth/xmlparse.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/xmlparse.cpp release.20115.0305gridedit/mythtv/libs/libmyth/xmlparse.cpp
13 13 #undef LoadImage 14 14 #endif 15 15 16 #define LOC QString("XMLParse: ") 17 #define LOC_WARN QString("XMLParse, Warning: ") 18 #define LOC_ERR QString("XMLParse, Error: ") 19 16 20 MPUBLIC QMap<QString, fontProp> globalFontMap; 17 21 18 22 XMLParse::XMLParse(void) … … 1442 1446 { 1443 1447 parseBlackHole(container, info); 1444 1448 } 1449 else if (info.tagName() == "grideditimage") 1450 { 1451 parseGridEditImage(container, info); 1452 } 1453 else if (info.tagName() == "grideditslider") 1454 { 1455 parseGridEditSlider(container, info); 1456 } 1445 1457 else if (info.tagName() == "area") 1446 1458 { 1447 1459 area = parseRect(getFirstText(info)); … … 3445 3457 container->AddType(bh); 3446 3458 } 3447 3459 3460 3461 void XMLParse::parseGridEditImage(LayerSet *container, QDomElement &element) 3462 { 3463 QRect area; 3464 QColor outlineColor; 3465 QColor cutColor; 3466 QColor cutPointColor; 3467 QColor highlightColor; 3468 bool haveOutlineColor = false; 3469 bool haveCutColor = false; 3470 bool haveCutPointColor = false; 3471 bool haveHighlightColor = false; 3472 bool highlightFrame = false; 3473 3474 QString name = element.attribute("name", ""); 3475 if (name.isNull() || name.isEmpty()) 3476 { 3477 VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditImage needs a name"); 3478 return; 3479 } 3480 QString highlight = element.attribute("highlightframe", ""); 3481 if (highlight == "true") 3482 highlightFrame = true; 3483 3484 for (QDomNode child = element.firstChild(); !child.isNull(); 3485 child = child.nextSibling()) 3486 { 3487 QDomElement info = child.toElement(); 3488 if (!info.isNull()) 3489 { 3490 if (info.tagName() == "area") 3491 { 3492 area = parseRect(getFirstText(info)); 3493 normalizeRect(area); 3494 } 3495 else if (info.tagName() == "outlinecolor") 3496 { 3497 haveOutlineColor = true; 3498 outlineColor = getFirstText(info); 3499 } 3500 else if (info.tagName() == "cutcolor") 3501 { 3502 haveCutColor = true; 3503 cutColor = getFirstText(info); 3504 } 3505 else if (info.tagName() == "cutpointcolor") 3506 { 3507 haveCutPointColor = true; 3508 cutPointColor = getFirstText(info); 3509 } 3510 else if (info.tagName() == "highlightcolor") 3511 { 3512 haveHighlightColor = true; 3513 highlightColor = getFirstText(info); 3514 } 3515 else 3516 { 3517 VERBOSE(VB_IMPORTANT, LOC_WARN + 3518 QString("Unknown tag '%1' in grideditimage '%2'") 3519 .arg(info.tagName()).arg(name)); 3520 return; 3521 } 3522 } 3523 } 3524 3525 if (!haveOutlineColor) 3526 { 3527 VERBOSE(VB_IMPORTANT, LOC_WARN + 3528 QString("Missing tag 'outlinecolor' in grideditimage '%1'") 3529 .arg(name)); 3530 return; 3531 } 3532 3533 if (!haveCutColor) 3534 { 3535 VERBOSE(VB_IMPORTANT, LOC_WARN + 3536 QString("Missing tag 'cutcolor' in grideditimage '%1'") 3537 .arg(name)); 3538 return; 3539 } 3540 3541 if (!haveCutPointColor) 3542 { 3543 VERBOSE(VB_IMPORTANT, LOC_WARN + 3544 QString("Missing tag 'cutpointcolor' in grideditimage '%1'") 3545 .arg(name)); 3546 return; 3547 } 3548 3549 if (highlightFrame && !haveHighlightColor) 3550 { 3551 VERBOSE(VB_IMPORTANT, LOC_WARN + 3552 QString("highlightframe specified but missing tag 'hightlightcolor' in grideditimage '%1'") 3553 .arg(name)); 3554 return; 3555 } 3556 3557 3558 UIGridEditImageType *gei = new UIGridEditImageType(name); 3559 gei->SetScreen(wmult, hmult); 3560 gei->setArea(area); 3561 gei->setOutlineColor(outlineColor); 3562 gei->setCutColor(cutColor); 3563 gei->setCutPointColor(cutPointColor); 3564 gei->setHighlightColor(highlightColor); 3565 gei->setHighlightFrame(highlightFrame); 3566 gei->SetParent(container); 3567 gei->calculateScreenArea(); 3568 gei->clearPixmap(false); 3569 container->AddType(gei); 3570 } 3571 3572 void XMLParse::parseGridEditSlider(LayerSet *container, QDomElement &element) 3573 { 3574 QRect area; 3575 QColor fillColor; 3576 QColor cutColor; 3577 QColor inCutColor; 3578 QColor cutPointColor; 3579 QColor positionColor; 3580 bool haveFillColor = false; 3581 bool haveCutColor = false; 3582 bool haveInCutColor = false; 3583 bool haveCutPointColor = false; 3584 bool havePositionColor = false; 3585 3586 QString name = element.attribute("name", ""); 3587 if (name.isNull() || name.isEmpty()) 3588 { 3589 VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditSlider needs a name"); 3590 return; 3591 } 3592 3593 for (QDomNode child = element.firstChild(); !child.isNull(); 3594 child = child.nextSibling()) 3595 { 3596 QDomElement info = child.toElement(); 3597 if (!info.isNull()) 3598 { 3599 if (info.tagName() == "area") 3600 { 3601 area = parseRect(getFirstText(info)); 3602 normalizeRect(area); 3603 } 3604 else if (info.tagName() == "fillcolor") 3605 { 3606 haveFillColor = true; 3607 fillColor = getFirstText(info); 3608 } 3609 else if (info.tagName() == "cutcolor") 3610 { 3611 haveCutColor = true; 3612 cutColor = getFirstText(info); 3613 } 3614 else if (info.tagName() == "incutcolor") 3615 { 3616 haveInCutColor = true; 3617 inCutColor = getFirstText(info); 3618 } 3619 else if (info.tagName() == "cutpointcolor") 3620 { 3621 haveCutPointColor = true; 3622 cutPointColor = getFirstText(info); 3623 } 3624 else if (info.tagName() == "positioncolor") 3625 { 3626 havePositionColor = true; 3627 positionColor = getFirstText(info); 3628 } 3629 else 3630 { 3631 VERBOSE(VB_IMPORTANT, LOC_WARN + 3632 QString("Unknown tag '%1' in grideditslider '%2'") 3633 .arg(info.tagName()).arg(name)); 3634 return; 3635 } 3636 } 3637 } 3638 3639 if (!haveFillColor) 3640 { 3641 VERBOSE(VB_IMPORTANT, LOC_WARN + 3642 QString("Missing tag 'fillcolor' in grideditslider '%1'") 3643 .arg(name)); 3644 return; 3645 } 3646 3647 if (!haveCutColor) 3648 { 3649 VERBOSE(VB_IMPORTANT, LOC_WARN + 3650 QString("Missing tag 'cutcolor' in grideditslider '%1'") 3651 .arg(name)); 3652 return; 3653 } 3654 3655 if (!haveInCutColor) 3656 { 3657 VERBOSE(VB_IMPORTANT, LOC_WARN + 3658 QString("Missing tag 'incutcolor' in grideditslider '%1'") 3659 .arg(name)); 3660 return; 3661 } 3662 3663 if (!haveCutPointColor) 3664 { 3665 VERBOSE(VB_IMPORTANT, LOC_WARN + 3666 QString("Missing tag 'cutpointcolor' in grideditslider '%1'") 3667 .arg(name)); 3668 return; 3669 } 3670 3671 if (!havePositionColor) 3672 { 3673 VERBOSE(VB_IMPORTANT, LOC_WARN + 3674 QString("Missing tag 'positioncolor' in grideditslider '%1'") 3675 .arg(name)); 3676 return; 3677 } 3678 3679 UIGridEditSliderType *ges = new UIGridEditSliderType(name); 3680 ges->SetScreen(wmult, hmult); 3681 ges->setArea(area); 3682 ges->setFillColor(fillColor); 3683 ges->setCutColor(cutColor); 3684 ges->setInCutColor(inCutColor); 3685 ges->setCutPointColor(cutPointColor); 3686 ges->setPositionColor(positionColor); 3687 ges->SetParent(container); 3688 ges->calculateScreenArea(); 3689 container->AddType(ges); 3690 } 3691 3448 3692 void XMLParse::parseListBtnArea(LayerSet *container, QDomElement &element) 3449 3693 { 3450 3694 int context = -1; -
mythtv/libs/libmyth/xmlparse.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmyth/xmlparse.h release.20115.0305gridedit/mythtv/libs/libmyth/xmlparse.h
49 49 void parseCheckBox(LayerSet *, QDomElement &); 50 50 void parseSelector(LayerSet *, QDomElement &); 51 51 void parseBlackHole(LayerSet *, QDomElement &); 52 void parseGridEditImage(LayerSet *, QDomElement &); 53 void parseGridEditSlider(LayerSet *, QDomElement &); 52 54 void parseListBtnArea(LayerSet *, QDomElement &); 53 55 void parseListTreeArea(LayerSet *, QDomElement &); 54 56 void parseKeyboard(LayerSet *, QDomElement &); -
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
53 53 #include "interactivetv.h" 54 54 #include "util-osx-cocoa.h" 55 55 56 #include "grideditcutpoints.h" 57 56 58 extern "C" { 57 59 #include "vbitext/vbi.h" 58 60 #include "vsync.h" … … 157 159 decoder_thread_alive(true), killplayer(false), 158 160 killvideo(false), livetv(false), 159 161 watchingrecording(false), editmode(false), 162 hideedits(false), 160 163 resetvideo(false), using_null_videoout(false), 161 164 no_audio_in(false), no_audio_out(false), 162 165 transcoding(false), … … 166 169 bookmarkseek(0), previewFromBookmark(false), 167 170 // Seek 168 171 fftime(0), seekamountpos(4), 169 seekamount(30), exactseeks(false), 172 allow_pagesize(false), half_page(0), 173 seekamount(30), seekamounttext("30 Frames"), 174 exactseeks(false), 170 175 // Playback misc. 171 176 videobuf_retries(0), framesPlayed(0), 172 177 totalFrames(0), totalLength(0), … … 218 223 yuv_need_copy(false), yuv_desired_size(0,0), 219 224 yuv_scaler(NULL), yuv_frame_scaled(NULL), 220 225 yuv_scaler_in_size(0,0), yuv_scaler_out_size(0,0), 226 // Grid Editing 227 grid_edit_image_scaler(NULL), grid_edit_image_small_scaler(NULL), 228 grid_edit_image_buffer_yuv(NULL), grid_edit_image_small_buffer_yuv(NULL), 229 grid_edit_image_buffer_rgb(NULL), grid_edit_image_small_buffer_rgb(NULL), 230 grid_edit_image_buffer_length(0), grid_edit_image_small_buffer_length(0), 231 grid_edit_image_in_size(-1, -1), 232 221 233 // Filters 222 234 videoFiltersForProgram(""), videoFiltersOverride(""), 223 235 postfilt_width(0), postfilt_height(0), … … 388 400 output_jmeter = NULL; 389 401 } 390 402 403 ClearScreenGrab(); 404 391 405 ShutdownYUVResize(); 392 406 } 393 407 … … 1526 1540 return retval; 1527 1541 } 1528 1542 1543 1544 bool NuppelVideoPlayer::GetScreenGrabsOfCurrentFrame(QImage &normal, QImage &small) 1545 { 1546 1547 unsigned char *data = NULL; 1548 VideoFrame *frame = NULL; 1549 AVPicture orig; 1550 AVPicture scaled; 1551 AVPicture scaled_small; 1552 bzero(&orig, sizeof(AVPicture)); 1553 bzero(&scaled, sizeof(AVPicture)); 1554 bzero(&scaled_small, sizeof(AVPicture)); 1555 1556 int vw, vh; 1557 if (!(frame = GetCurrentFrame(vw, vh))) 1558 { 1559 return false; 1560 } 1561 1562 if (!(data = frame->buf)) 1563 { 1564 ReleaseCurrentFrame(frame); 1565 return false;; 1566 } 1567 1568 // Check to see if the screen dimensions have changed 1569 // Probably shouldn't happen in normal use. 1570 if (grid_edit_image_in_size != video_dim) 1571 SetupScreenGrab(); 1572 1573 avpicture_fill(&orig, data, PIX_FMT_YUV420P, 1574 video_dim.width(), video_dim.height()); 1575 1576 avpicture_deinterlace(&orig, &orig, PIX_FMT_YUV420P, 1577 video_dim.width(), video_dim.height()); 1578 1579 // Rescale to the normal size 1580 avpicture_fill(&scaled, grid_edit_image_buffer_yuv, PIX_FMT_YUV420P, 1581 grid_edit_image_size.width(), 1582 grid_edit_image_size.height()); 1583 1584 img_resample(grid_edit_image_scaler, &scaled, &orig); 1585 1586 // Don't need the current frame anymore so release it 1587 ReleaseCurrentFrame(frame); 1588 1589 // Rescale to the small size 1590 avpicture_fill(&scaled_small, grid_edit_image_small_buffer_yuv, PIX_FMT_YUV420P, 1591 grid_edit_image_small_size.width(), 1592 grid_edit_image_small_size.height()); 1593 1594 img_resample(grid_edit_image_small_scaler, &scaled_small, &scaled); 1595 1596 // Convert scaled and scaled_small from YUV to RGB 1597 1598 // scaled first 1599 uint w = grid_edit_image_size.width(); 1600 uint h = grid_edit_image_size.height(); 1601 unsigned char *yuv_buf = grid_edit_image_buffer_yuv; 1602 unsigned char *rgb_buf = grid_edit_image_buffer_rgb; 1603 yuv2argb_conv(rgb_buf, 1604 yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4), 1605 w, h, w * 4, w, w / 2, 0); 1606 1607 // scaled_small next 1608 w = grid_edit_image_small_size.width(); 1609 h = grid_edit_image_small_size.height(); 1610 yuv_buf = grid_edit_image_small_buffer_yuv; 1611 rgb_buf = grid_edit_image_small_buffer_rgb; 1612 yuv2argb_conv(rgb_buf, 1613 yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4), 1614 w, h, w * 4, w, w / 2, 0); 1615 1616 #ifdef MMX 1617 #define _RGBSWAP .swapRGB() 1618 #endif 1619 1620 normal = QImage(grid_edit_image_buffer_rgb, 1621 grid_edit_image_size.width(), grid_edit_image_size.height(), 1622 32, NULL, 65536 * 65536, QImage::LittleEndian)_RGBSWAP; 1623 1624 small = QImage(grid_edit_image_small_buffer_rgb, 1625 grid_edit_image_small_size.width(), grid_edit_image_small_size.height(), 1626 32, NULL, 65536 * 65536, QImage::LittleEndian)_RGBSWAP; 1627 1628 return true; 1629 } 1630 1529 1631 void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame) 1530 1632 { 1531 1633 if (frame) … … 2926 3028 } 2927 3029 } 2928 3030 3031 void NuppelVideoPlayer::SetScreenGrabSizes(QSize normal, QSize small) 3032 { 3033 grid_edit_image_size = normal; 3034 grid_edit_image_small_size = small; 3035 3036 SetupScreenGrab(); 3037 VERBOSE(VB_GENERAL, QString("Main Image = (%1, %2) from (%3, %4)") 3038 .arg(grid_edit_image_size.width()) 3039 .arg(grid_edit_image_size.height()) 3040 .arg(normal.width()).arg(normal.height())); 3041 VERBOSE(VB_GENERAL, QString("Small Image = (%1, %2) from (%3, %4)") 3042 .arg(grid_edit_image_small_size.width()) 3043 .arg(grid_edit_image_small_size.height()) 3044 .arg(small.width()).arg(small.height())); 3045 3046 } 3047 3048 void NuppelVideoPlayer::ClearScreenGrab() 3049 { 3050 if (grid_edit_image_scaler) 3051 { 3052 img_resample_close(grid_edit_image_scaler); 3053 grid_edit_image_scaler = NULL; 3054 } 3055 3056 if (grid_edit_image_small_scaler) 3057 { 3058 img_resample_close(grid_edit_image_small_scaler); 3059 grid_edit_image_small_scaler=NULL; 3060 } 3061 3062 if (grid_edit_image_buffer_yuv) 3063 { 3064 delete grid_edit_image_buffer_yuv; 3065 grid_edit_image_buffer_yuv=NULL; 3066 } 3067 3068 if (grid_edit_image_small_buffer_yuv) 3069 { 3070 delete grid_edit_image_small_buffer_yuv; 3071 grid_edit_image_small_buffer_yuv=NULL; 3072 } 3073 3074 if (grid_edit_image_buffer_rgb) 3075 { 3076 delete grid_edit_image_buffer_rgb; 3077 grid_edit_image_buffer_rgb=NULL; 3078 } 3079 3080 if (grid_edit_image_small_buffer_rgb) 3081 { 3082 delete grid_edit_image_small_buffer_rgb; 3083 grid_edit_image_small_buffer_rgb=NULL; 3084 } 3085 } 3086 3087 void NuppelVideoPlayer::SetupScreenGrab() 3088 { 3089 ClearScreenGrab(); 3090 grid_edit_image_in_size = video_dim; 3091 3092 // Normalize the output sizes. 3093 // This is necessary to preserve the aspect ratio 3094 3095 QSize tmpsize = grid_edit_image_size; 3096 grid_edit_image_size = video_dim; 3097 grid_edit_image_size.scale(tmpsize, QSize::ScaleMin); 3098 3099 tmpsize = grid_edit_image_small_size; 3100 grid_edit_image_small_size = video_dim; 3101 grid_edit_image_small_size.scale(tmpsize, QSize::ScaleMin); 3102 3103 grid_edit_image_size = QSize(grid_edit_image_size.width() & ~0x7, 3104 grid_edit_image_size.height() & ~0x7); 3105 grid_edit_image_small_size = QSize(grid_edit_image_small_size.width() & ~0x7, 3106 grid_edit_image_small_size.height() & ~0x7); 3107 3108 // Do normal first 3109 uint sz = grid_edit_image_size.width() * grid_edit_image_size.height(); 3110 grid_edit_image_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128]; 3111 grid_edit_image_buffer_rgb = new unsigned char[sz * 4 + 128]; 3112 3113 grid_edit_image_scaler = img_resample_init( 3114 grid_edit_image_size.width(), grid_edit_image_size.height(), 3115 grid_edit_image_in_size.width(), grid_edit_image_in_size.height()); 3116 3117 // Then small 3118 sz = grid_edit_image_small_size.width() * grid_edit_image_small_size.height(); 3119 grid_edit_image_small_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128]; 3120 grid_edit_image_small_buffer_rgb = new unsigned char[sz * 4 + 128]; 3121 3122 // Resize from normal to small 3123 grid_edit_image_small_scaler = img_resample_init( 3124 grid_edit_image_small_size.width(), grid_edit_image_small_size.height(), 3125 grid_edit_image_size.width(), grid_edit_image_size.height()); 3126 } 3127 2929 3128 void NuppelVideoPlayer::DisplayNormalFrame(void) 2930 3129 { 2931 3130 SetVideoActuallyPaused(false); … … 4989 5188 4990 5189 dialogname = ""; 4991 5190 5191 osd->HideAllExcept("editmode"); 5192 4992 5193 QMap<QString, QString> infoMap; 4993 5194 m_playbackinfo->ToMap(infoMap); 4994 5195 osd->SetText("editmode", infoMap, -1); … … 5044 5245 m_playbackinfo->SetEditing(false); 5045 5246 } 5046 5247 5248 bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame) 5249 { 5250 bool tmpexactseeks = exactseeks; 5251 GetDecoder()->setExactSeeks(true); 5252 5253 // VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2") 5254 // .arg(GetFramesPlayed()) 5255 // .arg(targetFrame)); 5256 5257 if (framesPlayed > targetFrame) 5258 { 5259 // seek back 5260 rewindtime = framesPlayed - targetFrame; 5261 while (rewindtime != 0) 5262 usleep(1000); 5263 } 5264 else 5265 { 5266 // seek forward 5267 fftime = targetFrame - framesPlayed; 5268 while (fftime != 0) 5269 usleep(1000); 5270 5271 } 5272 // VERBOSE(VB_GENERAL, QString("After current frame = %1") 5273 // .arg(GetFramesPlayed())); 5274 GetDecoder()->setExactSeeks(tmpexactseeks); 5275 return (targetFrame == framesPlayed); 5276 } 5277 5278 void NuppelVideoPlayer::EditHandleClearMap() 5279 { 5280 QMap<long long, int>::Iterator it; 5281 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5282 osd->HideEditArrow(it.key(), it.data()); 5283 5284 deleteMap.clear(); 5285 UpdateEditSlider(); 5286 } 5287 5288 void NuppelVideoPlayer::EditHandleInvertMap() 5289 { 5290 QMap<long long, int>::Iterator it; 5291 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5292 ReverseMark(it.key()); 5293 5294 UpdateEditSlider(); 5295 UpdateTimeDisplay(); 5296 } 5297 5298 void NuppelVideoPlayer::EditHandleLoadCommSkip() 5299 { 5300 if (hascommbreaktable) 5301 { 5302 commBreakMapLock.lock(); 5303 QMap<long long, int>::Iterator it; 5304 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5305 { 5306 if (!deleteMap.contains(it.key())) 5307 { 5308 if (it.data() == MARK_COMM_START) 5309 AddMark(it.key(), MARK_CUT_START); 5310 else 5311 AddMark(it.key(), MARK_CUT_END); 5312 } 5313 } 5314 commBreakMapLock.unlock(); 5315 UpdateEditSlider(); 5316 UpdateTimeDisplay(); 5317 } 5318 } 5319 5047 5320 bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e) 5048 5321 { 5049 5322 bool handled = false; … … 5123 5396 UpdateTimeDisplay(); 5124 5397 } 5125 5398 else if (action == "CLEARMAP") 5126 { 5127 QMap<long long, int>::Iterator it; 5128 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5129 osd->HideEditArrow(it.key(), it.data()); 5130 5131 deleteMap.clear(); 5132 UpdateEditSlider(); 5133 } 5399 EditHandleClearMap(); 5134 5400 else if (action == "INVERTMAP") 5135 { 5136 QMap<long long, int>::Iterator it; 5137 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5138 ReverseMark(it.key()); 5139 5140 UpdateEditSlider(); 5141 UpdateTimeDisplay(); 5142 } 5401 EditHandleInvertMap(); 5143 5402 else if (action == "LOADCOMMSKIP") 5144 { 5145 if (hascommbreaktable) 5146 { 5147 commBreakMapLock.lock(); 5148 QMap<long long, int>::Iterator it; 5149 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5150 { 5151 if (!deleteMap.contains(it.key())) 5152 { 5153 if (it.data() == MARK_COMM_START) 5154 AddMark(it.key(), MARK_CUT_START); 5155 else 5156 AddMark(it.key(), MARK_CUT_END); 5157 } 5158 } 5159 commBreakMapLock.unlock(); 5160 UpdateEditSlider(); 5161 UpdateTimeDisplay(); 5162 } 5163 } 5403 EditHandleLoadCommSkip(); 5164 5404 else if (action == "PREVCUT") 5165 5405 { 5166 5406 int old_seekamount = seekamount; … … 5206 5446 UpdateEditSlider(); 5207 5447 UpdateTimeDisplay(); 5208 5448 } 5209 else if (action == "ESCAPE" || action == "MENU" || 5210 action == "TOGGLEEDIT") 5449 else if (action == "TOGGLEEDIT" || action == "MENU") 5450 m_tv->ShowEditRecordingGrid(); 5451 else if (action == "ESCAPE") 5211 5452 { 5212 5453 DisableEdit(); 5213 5454 retval = false; … … 5220 5461 return retval; 5221 5462 } 5222 5463 5464 void NuppelVideoPlayer::ShowEditRecordingGrid(void) 5465 { 5466 // Completely hide the OSD 5467 osd->HideAll(); 5468 hideedits = true; 5469 5470 GridEditCutpoints::Run(this); 5471 5472 ClearScreenGrab(); 5473 5474 allow_pagesize = false; 5475 hideedits = false; 5476 5477 // Show OSD 5478 5479 QMap<QString, QString> infoMap; 5480 m_playbackinfo->ToMap(infoMap); 5481 osd->SetText("editmode", infoMap, -1); 5482 5483 UpdateEditSlider(); 5484 UpdateTimeDisplay(); 5485 if (seekamountpos == 3 || seekamountpos == 4) 5486 UpdateSeekAmount(true); 5487 else 5488 UpdateSeekAmountDisplay(); 5489 5490 QMap<long long, int>::Iterator it; 5491 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5492 AddMark(it.key(), it.data()); 5493 } 5494 5223 5495 AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const 5224 5496 { 5225 5497 if (videoOutput) … … 5311 5583 5312 5584 void NuppelVideoPlayer::UpdateSeekAmount(bool up) 5313 5585 { 5314 if (seekamountpos > 0 && !up) 5315 seekamountpos--; 5316 if (seekamountpos < 9 && up) 5317 seekamountpos++; 5586 if (up) 5587 { 5588 if (seekamountpos < 11) 5589 seekamountpos++; 5590 if (allow_pagesize) 5591 { 5592 if (seekamountpos == 1) 5593 seekamountpos = 2; 5594 } 5595 else 5596 { 5597 if (seekamountpos == 3 || seekamountpos == 4) 5598 seekamountpos = 5; 5599 } 5600 } 5601 else 5602 { 5603 if (seekamountpos > 0) 5604 seekamountpos--; 5605 if (allow_pagesize) 5606 { 5607 if (seekamountpos == 1) 5608 seekamountpos =0; 5609 } 5610 else 5611 { 5612 if (seekamountpos == 3 || seekamountpos == 4) 5613 seekamountpos = 2; 5614 } 5615 } 5318 5616 5319 QString text = "";5617 QString text; 5320 5618 5321 5619 switch (seekamountpos) 5322 5620 { 5323 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5324 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5325 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5326 case 3: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5327 case 4: text = QObject::tr("1 second"); seekamount = (int)roundf(video_frame_rate); break; 5328 case 5: text = QObject::tr("5 seconds"); seekamount = (int)roundf(video_frame_rate * 5); break; 5329 case 6: text = QObject::tr("20 seconds"); seekamount = (int)roundf(video_frame_rate * 20); break; 5330 case 7: text = QObject::tr("1 minute"); seekamount = (int)roundf(video_frame_rate * 60); break; 5331 case 8: text = QObject::tr("5 minutes"); seekamount = (int)roundf(video_frame_rate * 300); break; 5332 case 9: text = QObject::tr("10 minutes"); seekamount = (int)roundf(video_frame_rate * 600); break; 5333 default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break; 5621 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5622 5623 // Only for non-edit grid 5624 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5625 // Only for non-edit grid 5626 5627 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5628 5629 // Case 3 & 4 are for the edit grid only 5630 case 3: text = QObject::tr("1/2 Page"); seekamount = half_page; break; 5631 case 4: text = QObject::tr("Full Page"); seekamount = 2*half_page; break; 5632 // Case 3 & 4 are for the edit grid only 5633 5634 case 5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5635 case 6: text = QObject::tr("1 second"); seekamount = (int)roundf(video_frame_rate); break; 5636 case 7: text = QObject::tr("5 seconds"); seekamount = (int)roundf(video_frame_rate * 5); break; 5637 case 8: text = QObject::tr("20 seconds"); seekamount = (int)roundf(video_frame_rate * 20); break; 5638 case 9: text = QObject::tr("1 minute"); seekamount = (int)roundf(video_frame_rate * 60); break; 5639 case 10: text = QObject::tr("5 minutes"); seekamount = (int)roundf(video_frame_rate * 300); break; 5640 case 11: text = QObject::tr("10 minutes"); seekamount = (int)roundf(video_frame_rate * 600); break; 5641 default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break; 5334 5642 } 5335 5643 5644 seekamounttext = text; 5645 UpdateSeekAmountDisplay(); 5646 } 5647 5648 void NuppelVideoPlayer::UpdateSeekAmountDisplay(void) 5649 { 5336 5650 QMap<QString, QString> infoMap; 5337 infoMap["seekamount"] = text; 5338 osd->SetText("editmode", infoMap, -1); 5651 infoMap["seekamount"] = seekamounttext; 5652 if (!hideedits) 5653 osd->SetText("editmode", infoMap, -1); 5339 5654 } 5340 5655 5341 5656 void NuppelVideoPlayer::UpdateTimeDisplay(void) … … 5365 5680 infoMap["timedisplay"] = timestr; 5366 5681 infoMap["framedisplay"] = framestr; 5367 5682 infoMap["cutindicator"] = cutmarker; 5368 osd->SetText("editmode", infoMap, -1); 5683 if (!hideedits) 5684 osd->SetText("editmode", infoMap, -1); 5369 5685 } 5370 5686 5371 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)5687 DeletePointInfo NuppelVideoPlayer::GetDeletePointInfo(long long frame, bool allowSelectNear) 5372 5688 { 5373 bool deletepoint = false; 5374 bool cut_after = false; 5375 int direction = 0; 5689 DeletePointInfo retval; 5376 5690 5377 5691 if(!deleteMap.isEmpty()) 5378 5692 { 5379 5693 QMap<long long, int>::ConstIterator iter = deleteMap.begin(); 5380 5694 5381 while((iter != deleteMap.end()) && (iter.key() < frame sPlayed))5695 while((iter != deleteMap.end()) && (iter.key() < frame)) 5382 5696 ++iter; 5383 5697 5384 5698 if (iter == deleteMap.end()) 5385 5699 { 5386 5700 --iter; 5387 cut_after = !iter.data();5701 retval.cut_after = !iter.data(); 5388 5702 } 5389 else if((iter != deleteMap.begin()) && (iter.key() != frame sPlayed))5703 else if((iter != deleteMap.begin()) && (iter.key() != frame)) 5390 5704 { 5391 5705 long long value = iter.key(); 5392 if((frame sPlayed - (--iter).key()) > (value - framesPlayed))5706 if((frame - (--iter).key()) > (value - frame)) 5393 5707 { 5394 cut_after = !iter.data();5708 retval.cut_after = !iter.data(); 5395 5709 ++iter; 5396 5710 } 5397 5711 else 5398 cut_after = !iter.data();5712 retval.cut_after = !iter.data(); 5399 5713 } 5400 5714 5401 direction = iter.data();5402 deleteframe = iter.key();5715 retval.direction = iter.data(); 5716 retval.deleteframe = iter.key(); 5403 5717 5404 if ((absLongLong( deleteframe - framesPlayed) <5718 if ((absLongLong(retval.deleteframe - frame) < 5405 5719 (int)ceil(20 * video_frame_rate)) && !allowSelectNear) 5406 5720 { 5407 deletepoint = true;5721 retval.deletepoint = true; 5408 5722 } 5409 5723 } 5724 return retval; 5725 } 5410 5726 5411 if (deletepoint) 5727 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear) 5728 { 5729 DeletePointInfo dpi = GetDeletePointInfo(framesPlayed, allowSelectNear); 5730 deleteframe = dpi.deleteframe; 5731 5732 if (dpi.deletepoint) 5412 5733 { 5413 5734 QString message = QObject::tr("You are close to an existing cut point. " 5414 5735 "Would you like to:"); … … 5416 5737 QString option2 = QObject::tr("Move this cut point to the current " 5417 5738 "position"); 5418 5739 QString option3 = QObject::tr("Flip directions - delete to the "); 5419 if (d irection == 0)5740 if (dpi.direction == 0) 5420 5741 option3 += QObject::tr("right"); 5421 5742 else 5422 5743 option3 += QObject::tr("left"); … … 5446 5767 options += option1; 5447 5768 options += option2; 5448 5769 5449 osd->NewDialogBox(dialogname, message, options, -1, cut_after);5770 osd->NewDialogBox(dialogname, message, options, -1, dpi.cut_after); 5450 5771 } 5451 5772 } 5452 5773 … … 5497 5818 5498 5819 void NuppelVideoPlayer::UpdateEditSlider(void) 5499 5820 { 5500 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5821 if (!hideedits) 5822 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5501 5823 } 5502 5824 5503 5825 void NuppelVideoPlayer::AddMark(long long frames, int type) 5504 5826 { 5505 5827 deleteMap[frames] = type; 5506 osd->ShowEditArrow(frames, totalFrames, type); 5828 if (!hideedits) 5829 osd->ShowEditArrow(frames, totalFrames, type); 5507 5830 } 5508 5831 5509 5832 void NuppelVideoPlayer::DeleteMark(long long frames) 5510 5833 { 5511 osd->HideEditArrow(frames, deleteMap[frames]); 5834 if (!hideedits) 5835 osd->HideEditArrow(frames, deleteMap[frames]); 5512 5836 deleteMap.remove(frames); 5513 5837 } 5514 5838 5515 5839 void NuppelVideoPlayer::ReverseMark(long long frames) 5516 5840 { 5517 osd->HideEditArrow(frames, deleteMap[frames]); 5841 if (!hideedits) 5842 osd->HideEditArrow(frames, deleteMap[frames]); 5518 5843 5519 5844 if (deleteMap[frames] == MARK_CUT_END) 5520 5845 deleteMap[frames] = MARK_CUT_START; 5521 5846 else 5522 5847 deleteMap[frames] = MARK_CUT_END; 5523 5848 5524 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5849 if (!hideedits) 5850 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5851 } 5852 5853 long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right) 5854 { 5855 QMap<long long, int>::Iterator i = deleteMap.begin(); 5856 long long framenum = -1; 5857 long long seekcount = 0; 5858 if (right) 5859 { 5860 for (; i != deleteMap.end(); ++i) 5861 { 5862 if (i.key() > baseframe) 5863 { 5864 framenum = i.key(); 5865 break; 5866 } 5867 } 5868 if (framenum == -1) 5869 framenum = totalFrames; 5870 seekcount = framenum - baseframe; 5871 } 5872 else 5873 { 5874 for (; i != deleteMap.end(); ++i) 5875 { 5876 if (i.key() >= baseframe) 5877 break; 5878 framenum = i.key(); 5879 } 5880 if (framenum == -1) 5881 framenum = 0; 5882 seekcount = baseframe - framenum; 5883 } 5884 return seekcount; 5525 5885 } 5526 5886 5527 5887 void NuppelVideoPlayer::HandleArbSeek(bool right) 5528 5888 { 5529 5889 if (seekamount == -2) 5530 5890 { 5531 QMap<long long, int>::Iterator i = deleteMap.begin(); 5532 long long framenum = -1; 5891 long long seekcount = CalcCutPointSeek(framesPlayed, right); 5533 5892 if (right) 5534 5893 { 5535 for (; i != deleteMap.end(); ++i) 5536 { 5537 if (i.key() > framesPlayed) 5538 { 5539 framenum = i.key(); 5540 break; 5541 } 5542 } 5543 if (framenum == -1) 5544 framenum = totalFrames; 5545 5546 fftime = framenum - framesPlayed; 5894 fftime = seekcount; 5547 5895 while (fftime > 0) 5548 5896 usleep(1000); 5549 5897 } 5550 5898 else 5551 5899 { 5552 for (; i != deleteMap.end(); ++i) 5553 { 5554 if (i.key() >= framesPlayed) 5555 break; 5556 framenum = i.key(); 5557 } 5558 if (framenum == -1) 5559 framenum = 0; 5560 5561 rewindtime = framesPlayed - framenum; 5900 rewindtime = seekcount; 5562 5901 while (rewindtime > 0) 5563 5902 usleep(1000); 5564 5903 } … … 5589 5928 UpdateEditSlider(); 5590 5929 } 5591 5930 5931 int NuppelVideoPlayer::GetCutStatus(long long testframe) const 5932 { 5933 int retval = 0; 5934 QMap<long long, int>::const_iterator i; 5935 i = deleteMap.find(testframe); 5936 if (i == deleteMap.end()) { 5937 // testframe is not an explicit cutpoint 5938 // See if it is in a deleted area 5939 if (IsInDelete(testframe)) 5940 retval = 1; 5941 } else { 5942 int direction = i.data(); 5943 if (direction == 0) 5944 retval = 2; 5945 else 5946 retval = 3; 5947 } 5948 5949 return retval; 5950 } 5951 5592 5952 bool NuppelVideoPlayer::IsInDelete(long long testframe) const 5593 5953 { 5594 5954 long long startpos = 0; -
mythtv/libs/libmythtv/NuppelVideoPlayer.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/NuppelVideoPlayer.h release.20115.0305gridedit/mythtv/libs/libmythtv/NuppelVideoPlayer.h
100 100 kDisplayTeletextMenu = 0x40, 101 101 }; 102 102 103 class DeletePointInfo 104 { 105 public: 106 DeletePointInfo() : 107 deleteframe(0), deletepoint(false), cut_after(false), direction(0) {} 108 109 long long deleteframe; 110 bool deletepoint; 111 bool cut_after; 112 int direction; 113 }; 114 103 115 class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 104 116 { 117 friend class GridEditCutpoints; 118 friend class TV; 105 119 public: 106 120 NuppelVideoPlayer(QString inUseID = "Unknown", 107 121 const ProgramInfo *info = NULL); … … 270 284 bool EnableEdit(void); 271 285 bool DoKeypress(QKeyEvent *e); 272 286 bool GetEditMode(void) const { return editmode; } 287 bool GetHideEdits(void) const { return hideedits; } 273 288 274 289 // Decoder stuff.. 275 290 VideoFrame *GetNextVideoFrame(bool allow_unsafe = true); … … 289 304 void ShutdownYUVResize(void); 290 305 void SaveScreenshot(void); 291 306 307 // Edit stuff 308 bool EditSeekToFrame(long long targetFrame); 309 void SetScreenGrabSizes(QSize normal, QSize small); 310 bool GetScreenGrabsOfCurrentFrame(QImage & normal, QImage &small); // Get current frame 311 312 void EditHandleClearMap(); 313 void EditHandleInvertMap(); 314 void EditHandleLoadCommSkip(); 315 316 void ShowEditRecordingGrid(); 317 292 318 // Reinit 293 319 void ReinitOSD(void); 294 320 void ReinitVideo(void); … … 406 432 hidedvdbutton = hide; 407 433 } 408 434 435 // Stuf for GridEditCutpoints 436 long long CalcCutPointSeek(long long baseframe, bool right); 437 // returns 438 // 0 - no cut 439 // 1 - is deleted 440 // 2 - cut left 441 // 3 - cut right 442 int GetCutStatus(long long testframe) const; 443 long long GetSeekAmount() { return seekamount; } 444 QString GetSeekAmountText() { return seekamounttext; } 445 409 446 protected: 410 447 void DisplayPauseFrame(void); 411 448 void DisplayNormalFrame(void); … … 487 524 void HandleSelect(bool allowSelectNear = false); 488 525 void HandleResponse(void); 489 526 527 DeletePointInfo GetDeletePointInfo(long long frame, bool allowSelectNear); 528 void SetupScreenGrab(); 529 void ClearScreenGrab(); 530 490 531 void UpdateTimeDisplay(void); 532 int GetSeekAmountPos() { return seekamountpos; } 491 533 void UpdateSeekAmount(bool up); 534 void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; } 535 void UpdateSeekAmountDisplay(void); 492 536 void UpdateEditSlider(void); 493 537 494 538 // Private A/V Sync Stuff … … 560 604 bool livetv; 561 605 bool watchingrecording; 562 606 bool editmode; 607 bool hideedits; 563 608 bool resetvideo; 564 609 bool using_null_videoout; 565 610 bool no_audio_in; … … 579 624 long long fftime; 580 625 /// 1..9 == keyframe..10 minutes. 0 == cut point 581 626 int seekamountpos; 627 /// Used for Grid Edit logic 628 bool allow_pagesize; 629 int half_page; 582 630 /// Seekable frame increment when not using exact seeks. 583 631 /// Usually equal to keyframedist. 584 632 int seekamount; 633 QString seekamounttext; // OSD seek units 585 634 /// Iff true we ignore seek amount and try to seek to an 586 635 /// exact frame ignoring key frame restrictions. 587 636 bool exactseeks; … … 714 763 QMutex yuv_lock; 715 764 QWaitCondition yuv_wait; 716 765 766 // EditGrid still image capture 767 ImgReSampleContext *grid_edit_image_scaler; 768 ImgReSampleContext *grid_edit_image_small_scaler; 769 unsigned char *grid_edit_image_buffer_yuv; 770 unsigned char *grid_edit_image_small_buffer_yuv; 771 unsigned char *grid_edit_image_buffer_rgb; 772 unsigned char *grid_edit_image_small_buffer_rgb; 773 int grid_edit_image_buffer_length; 774 int grid_edit_image_small_buffer_length; 775 QSize grid_edit_image_in_size; 776 QSize grid_edit_image_size; 777 QSize grid_edit_image_small_size; 778 717 779 // Filters 718 780 QMutex videofiltersLock; 719 781 QString videoFiltersForProgram; -
mythtv/libs/libmythtv/grideditcutpoints.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditcutpoints.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/grideditcutpoints.cpp
1 #include <qapplication.h> 2 #include <qpainter.h> 3 #include <qfont.h> 4 #include <qsqldatabase.h> 5 #include <qsqlquery.h> 6 #include <math.h> 7 #include <qcursor.h> 8 #include <qapplication.h> 9 #include <qimage.h> 10 #include <qlayout.h> 11 #include <qlabel.h> 12 #include <qdatetime.h> 13 #include <qvgroupbox.h> 14 #include <qheader.h> 15 #include <qrect.h> 16 17 #include <unistd.h> 18 #include <iostream> 19 #include <algorithm> 20 using namespace std; 21 22 #include "mythcontext.h" 23 #include "mythdbcon.h" 24 #include "grideditcutpoints.h" 25 #include "grideditimages.h" 26 #include "NuppelVideoPlayer.h" 27 28 void GridEditCutpoints::Run(NuppelVideoPlayer *player) 29 { 30 VERBOSE(VB_GENERAL, "Starting"); 31 gContext->addCurrentLocation("GridEditCutpoints"); 32 33 GridEditCutpoints *er = new GridEditCutpoints(gContext->GetMainWindow(), 34 player, "editrecording"); 35 36 if (er->isValid()) 37 { 38 er->Show(); 39 er->displayInitialFrame(); 40 er->exec(); 41 } 42 43 delete er; 44 45 gContext->removeCurrentLocation(); 46 VERBOSE(VB_GENERAL, "Ending"); 47 } 48 49 GridEditCutpoints::GridEditCutpoints(MythMainWindow *parent, 50 NuppelVideoPlayer *player, const char *name) 51 : MythThemedDialog(parent, "grideditcutpoints", "", name) 52 { 53 m_player = player; 54 m_images = new GridEditImages(this, player); 55 56 int i; 57 m_gridimagemain = NULL; 58 for (i = m_gridimages.minIndex(); i < m_gridimages.maxIndex(); i++) 59 m_gridimages[i] = NULL; 60 61 usedSubVideoCount=0; 62 63 QSize videoSizeMain, videoSizeSmall; 64 65 m_gridimagemain = getUIGridEditImageType("mainvideo"); 66 if (m_gridimagemain) 67 videoSizeMain = m_gridimagemain->getScreenArea().size(); 68 else 69 { 70 VERBOSE(VB_IMPORTANT, "FATAL: Couldn't find mainedit:mainvideo"); 71 return; 72 } 73 74 // Small version of main frame 75 m_gridimages[0] = getUIGridEditImageType("video0"); 76 77 for (i = 1; i < m_gridimages.maxIndex(); i++) 78 { 79 QString p = QString("videop%1").arg(i); 80 QString m = QString("videom%1").arg(i); 81 82 // Minus frame i 83 m_gridimages[-i] = getUIGridEditImageType(m); 84 if (m_gridimages[-i]) 85 { 86 QSize tmpVideoSizeSmall = m_gridimages[-i]->getScreenArea().size(); 87 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 88 VERBOSE(VB_IMPORTANT, 89 QString("Multiple sizes found for edit videos (%1)").arg(m)); 90 else 91 videoSizeSmall = tmpVideoSizeSmall; 92 if (i > usedSubVideoCount) usedSubVideoCount=i; 93 } 94 95 m_gridimages[i] = getUIGridEditImageType(p); 96 if (m_gridimages[i]) 97 { 98 QSize tmpVideoSizeSmall = m_gridimages[i]->getScreenArea().size(); 99 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 100 VERBOSE(VB_IMPORTANT, 101 QString("Multiple sizes found for edit videos (%1)").arg(p)); 102 else 103 videoSizeSmall = tmpVideoSizeSmall; 104 if (i > usedSubVideoCount) usedSubVideoCount=i; 105 } 106 } 107 108 imageScreenArea = m_gridimages[-usedSubVideoCount]->getOuterBorder(); 109 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 110 if (m_gridimages[i]) 111 imageScreenArea = imageScreenArea.unite(m_gridimages[i]->getOuterBorder()); 112 113 m_images->SetVideoInfo(usedSubVideoCount, videoSizeMain, videoSizeSmall); 114 115 m_player->SetHalfPageSize(usedSubVideoCount); 116 m_slider = getUIGridEditSliderType("positionbar"); 117 if (!m_slider) 118 VERBOSE(VB_GENERAL, "Missing positionbar for GridEditCutpoints"); 119 120 // Get Status boxes 121 { 122 m_framenum = getUITextType("framenum"); 123 m_time = getUITextType("time"); 124 m_cutind = getUITextType("cutind"); 125 m_jumpstyle = getUITextType("jumpstyle"); 126 m_updatingind = getUITextType("updatingind"); 127 } 128 129 VERBOSE(VB_GENERAL, QString("main = (%1, %2) small = (%3, %4)") 130 .arg(videoSizeMain.width()).arg(videoSizeMain.height()) 131 .arg(videoSizeSmall.width()).arg(videoSizeSmall.height())); 132 133 slowMotionDirection = 1; // start off play forward 134 slowMotionActive = false; 135 readyForNextFrame = false; 136 slowMotionTimer = new QTimer(this); 137 QObject::connect(slowMotionTimer, SIGNAL(timeout()), 138 this, SLOT(updateSlowMotion())); 139 140 movingCutpoint = false; 141 // Create blank pixmaps... 142 143 updateBackground(); 144 145 updateStats(); 146 147 setNoErase(); 148 gContext->addListener(this); 149 150 updateForeground(); 151 } 152 153 GridEditCutpoints::~GridEditCutpoints() 154 { 155 if (m_images) 156 { 157 delete m_images; 158 m_images = NULL; 159 } 160 gContext->removeListener(this); 161 } 162 163 void GridEditCutpoints::displayInitialFrame() 164 { 165 refreshImages(); 166 refreshCutList(); 167 updateStats(); 168 SetUpdating(false); 169 } 170 171 void GridEditCutpoints::updateSlowMotion() 172 { 173 if (!slowMotionActive) 174 slowMotionTimer->stop(); 175 else if (readyForNextFrame && slowMotionDirection != 0) 176 { 177 readyForNextFrame=false; 178 179 if (slowMotionDirection > 0) 180 EditHandleRight(); 181 else if (slowMotionDirection < 0) 182 EditHandleLeft(); 183 } 184 } 185 186 187 void GridEditCutpoints::setSlowMotionSpeed() 188 { 189 // slowMotionDirection is max FPS 190 191 if (slowMotionDirection != 0) 192 { 193 int smd = slowMotionDirection; 194 if (smd < 0) smd = -smd; 195 int timeout = 1000 / smd; 196 197 slowMotionTimer->start(timeout); 198 } 199 SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection)); 200 } 201 202 203 void GridEditCutpoints::keyPressEvent(QKeyEvent *e) 204 { 205 // keyDown limits keyrepeats to prevent continued scrolling 206 // after key is released. Note: Qt's keycompress should handle 207 // this but will fail with fast key strokes and keyboard repeat 208 // enabled. Keys will not be marked as autorepeat and flood buffer. 209 // setFocusPolicy(QWidget::ClickFocus) in constructor is important 210 // or keyRelease events will not be received after a refocus. 211 212 bool handled = false; 213 214 QStringList actions; 215 gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions); 216 217 { 218 for (unsigned int i = 0; i < actions.size() && !handled; i++) 219 { 220 QString action = actions[i]; 221 handled = true; 222 223 if (action == "SELECT") 224 { 225 if (slowMotionActive) 226 { 227 slowMotionActive = false; 228 slowMotionTimer->stop(); 229 } 230 else if (movingCutpoint) 231 { 232 // Move cutpoint 233 m_player->DeleteMark(savedCutpoint); 234 m_player->AddMark(m_images->GetCurrentFrameNumber(), savedCutType); 235 movingCutpoint = false; 236 refreshCutList(); 237 refreshImages(); 238 } 239 else 240 handleSelect(); 241 } 242 else if (action == "PAUSE") 243 { 244 if (movingCutpoint) 245 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 246 "Moving Cutpoint", 247 "Slow Motion Unavailable when moving cutpoint"); 248 else if (slowMotionActive) 249 { 250 slowMotionActive = false; 251 slowMotionTimer->stop(); 252 } 253 } 254 else if (action == "SLOWMO") 255 { 256 if (movingCutpoint) 257 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 258 "Moving Cutpoint", 259 "Slow Motion Unavailable when moving cutpoint"); 260 else 261 { 262 if (slowMotionActive) 263 { 264 slowMotionActive = false; 265 slowMotionTimer->stop(); 266 } 267 else 268 { 269 slowMotionActive = true; 270 readyForNextFrame = true; 271 slowMotionDirection = 1; 272 273 // force to either 1 frame. 1/2 page or full page motion 274 int i; 275 // move to 1 frame if on cutpoint 276 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 277 m_player->UpdateSeekAmount(true); 278 279 // move to fullpage if higher 280 for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++) 281 m_player->UpdateSeekAmount(false); 282 283 setSlowMotionSpeed(); 284 } 285 } 286 } 287 else if (action == "LEFT") 288 { 289 if (slowMotionActive) 290 { 291 slowMotionDirection--; 292 setSlowMotionSpeed(); 293 } 294 else 295 { 296 SetUpdating(true); 297 EditHandleLeft(); 298 } 299 } 300 else if (action == "RIGHT" ) 301 { 302 if (slowMotionActive) 303 { 304 slowMotionDirection++; 305 setSlowMotionSpeed(); 306 } 307 else 308 { 309 SetUpdating(true); 310 EditHandleRight(); 311 } 312 } 313 else if (action == "UP") 314 { 315 m_player->UpdateSeekAmount(true); 316 updateStats(); 317 } 318 else if (action == "DOWN") 319 { 320 if ((movingCutpoint || slowMotionActive) && m_player->GetSeekAmountPos() == 2) 321 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 322 "Moving Cutpoint", 323 "CutPoint skip Unavailable"); 324 else 325 { 326 m_player->UpdateSeekAmount(false); 327 updateStats(); 328 } 329 } 330 else if (action == "CLEARMAP") 331 { 332 if (movingCutpoint || slowMotionActive) 333 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 334 "Moving Cutpoint", 335 "Clear Cut Map Unavailable"); 336 else 337 { 338 SetUpdating(true); 339 m_player->EditHandleClearMap(); 340 refreshCutList(); 341 updateStats(); 342 } 343 } 344 else if (action == "INVERTMAP") 345 { 346 if (movingCutpoint || slowMotionActive) 347 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 348 "Moving Cutpoint", 349 "Invert Cut Map Unavailable"); 350 else 351 { 352 SetUpdating(true); 353 m_player->EditHandleInvertMap(); 354 refreshCutList(); 355 updateStats(); 356 } 357 } 358 else if (action == "LOADCOMMSKIP") 359 { 360 if (movingCutpoint || slowMotionActive) 361 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 362 "Moving Cutpoint", 363 "Load Comm Skip Map Unavailable"); 364 else 365 { 366 SetUpdating(true); 367 m_player->EditHandleLoadCommSkip(); 368 refreshCutList(); 369 updateStats(); 370 } 371 } 372 else if (action == "PREVCUT") 373 { 374 if (movingCutpoint || slowMotionActive) 375 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 376 "Moving Cutpoint", 377 "Prev Cut Unavailable"); 378 else 379 { 380 SetUpdating(true); 381 EditHandlePrevCut(); 382 } 383 } 384 else if (action == "NEXTCUT") 385 { 386 if (movingCutpoint || slowMotionActive) 387 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 388 "Moving Cutpoint", 389 "Next Cut Unavailable"); 390 else 391 { 392 SetUpdating(true); 393 EditHandleNextCut(); 394 } 395 } 396 else if (action == "BIGJUMPREW") 397 { 398 SetUpdating(true); 399 EditHandleBigJumpRew(); 400 } 401 else if (action == "BIGJUMPFWD") 402 { 403 SetUpdating(true); 404 EditHandleBigJumpFwd(); 405 } 406 else if (action == "ESCAPE" && movingCutpoint) 407 movingCutpoint = false; 408 else if (action == "ESCAPE" || action == "TOGGLEEDIT" || 409 action == "MENU") 410 escape(); 411 else 412 handled = false; 413 414 if (movingCutpoint) 415 SetUpdating(true, "Moving Cutpoint"); 416 else if (!slowMotionActive) 417 SetUpdating(false); 418 } 419 } 420 421 if (!handled) 422 MythDialog::keyPressEvent(e); 423 } 424 425 void GridEditCutpoints::EditHandleLeft(int seektype) 426 { 427 long long seekamount = m_player->GetSeekAmount(); 428 bool cutpointseek = false; 429 430 if (seektype == -2 || seekamount == -2) 431 cutpointseek = true; 432 else 433 { 434 // seektype == 1 for normal, 10 for bigjump 435 seekamount *= seektype; 436 } 437 438 if (seekamount < 0) // Invalid -- keyframe 439 seekamount = 1; 440 441 m_images->SeekLeft(seekamount, cutpointseek); 442 443 refreshImages(); 444 updateStats(); 445 } 446 447 void GridEditCutpoints::EditHandleRight(int seektype) 448 { 449 long long seekamount = m_player->GetSeekAmount(); 450 bool cutpointseek=false; 451 452 if (seektype == -2 || seekamount == -2) 453 cutpointseek = true; 454 else 455 { 456 // seektype == 1 for normal, 10 for bigjump 457 seekamount *= seektype; 458 } 459 460 if (seekamount < 0) // Invalid -- keyframe 461 seekamount = 1; 462 463 m_images->SeekRight(seekamount, cutpointseek); 464 465 refreshImages(); 466 updateStats(); 467 } 468 469 void GridEditCutpoints::handleSelect(void) 470 { 471 bool needupdate = false; 472 // add / update cutpoint 473 // -or- 474 // delete / flip / move cutpoint 475 476 // if no cut points on screen 477 // "Delete Before" 478 // "Delete After" 479 480 // if on existing cutpoint 481 // "Delete cutpoint" 482 // "Flip directions" 483 484 // FIXME 485 // if a cutpoint exists on the screen but not on the current frame 486 // "Move to current frame" 487 // "Add new" 488 489 FrameStats fs = m_images->GetMainFrameStats(); 490 DeletePointInfo dpi = m_player->GetDeletePointInfo(fs.frameNumber, true); 491 492 if (fs.cutInd >= 2) 493 { 494 QString title = ""; 495 QString message = "Cutpoint exists:"; 496 QStringList buttons; 497 buttons.append("Delete cutpoint?"); 498 buttons.append("Move cutpoint?"); 499 if (fs.cutInd == 2) 500 buttons.append("Flip directions (Cut After)?"); 501 else 502 buttons.append("Flip directions (Cut Before)?"); 503 504 DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(), 505 title, message, buttons, kDialogCodeButton0); 506 507 508 if (dc != kDialogCodeRejected) 509 { 510 needupdate = true; 511 if (dc == kDialogCodeButton0) 512 // Delete cutpoint 513 m_player->DeleteMark(fs.frameNumber); 514 515 else if (dc == kDialogCodeButton1) 516 { 517 // Move cutpoint 518 savedCutpoint = fs.frameNumber; 519 savedCutType = m_player->deleteMap[fs.frameNumber]; 520 movingCutpoint = true; 521 // Ensure we're at least at 1 frame motion 522 int i; 523 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 524 m_player->UpdateSeekAmount(true); 525 526 } 527 else if (dc == kDialogCodeButton2) 528 // Flip 529 m_player->ReverseMark(fs.frameNumber); 530 } 531 } 532 else 533 { 534 QString title = ""; 535 QString message = "Insert New Cutpoint?"; 536 QStringList buttons; 537 buttons.append("Delete before this frame"); 538 buttons.append("Delete after this frame"); 539 DialogCode default_cut = (dpi.cut_after ? kDialogCodeButton1: kDialogCodeButton0); 540 DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(), 541 title, message, buttons, default_cut); 542 543 if (dc != kDialogCodeRejected) 544 { 545 needupdate = true; 546 if (dc == kDialogCodeButton0) 547 // Delete left 548 m_player->AddMark(fs.frameNumber, MARK_CUT_END); 549 550 else if (dc == kDialogCodeButton1) 551 // Delete Right 552 m_player->AddMark(fs.frameNumber, MARK_CUT_START); 553 } 554 } 555 556 if (needupdate) 557 { 558 refreshCutList(); 559 refreshImages(); 560 } 561 } 562 563 void GridEditCutpoints::refreshImages() 564 { 565 m_images->refreshImages(m_gridimagemain, m_gridimages, false); 566 repaint(m_gridimagemain->getOuterBorder(), false); 567 repaint(imageScreenArea, false); 568 } 569 570 void GridEditCutpoints::refreshCutList() 571 { 572 m_images->refreshCutList(m_gridimagemain, m_gridimages); 573 refreshSlider(); 574 } 575 576 void GridEditCutpoints::refreshSlider() 577 { 578 if (!m_slider) 579 return; 580 581 m_slider->ClearAll(); 582 583 const int CUT_LEFT = 0; 584 const int CUT_RIGHT = 1; 585 586 long long startpos = 0; 587 long long endpos = 0; 588 589 int lastdirection = CUT_LEFT; 590 591 QMap<long long, int> & deleteMap = m_player->deleteMap; 592 QMap<long long, int>::Iterator i = deleteMap.begin(); 593 for (; i != deleteMap.end(); ++i) 594 { 595 long long frame = i.key(); 596 int direction = i.data(); 597 598 if (direction == CUT_LEFT) 599 { 600 endpos = frame; 601 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 602 603 startpos = frame; 604 lastdirection = CUT_LEFT; 605 } 606 else if (direction == CUT_RIGHT) 607 { 608 if (lastdirection == CUT_RIGHT) 609 { 610 // continuing within a cutpoint 611 endpos = frame; 612 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 613 } 614 615 startpos = frame; 616 lastdirection = CUT_RIGHT; 617 } 618 } 619 620 if (lastdirection == CUT_RIGHT) 621 { 622 // continuing within a cutpoint 623 endpos = m_images->GetMaxFrameNumber(); 624 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 625 } 626 } 627 628 void 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 682 void 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 690 void 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 706 void GridEditCutpoints::cacheFramesAreReady() 707 { 708 if (slowMotionActive) 709 { 710 readyForNextFrame=true; 711 if (!slowMotionTimer->isActive()) 712 slowMotionTimer->start(0); 713 } 714 } 715 -
mythtv/libs/libmythtv/grideditcutpoints.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditcutpoints.h release.20115.0305gridedit/mythtv/libs/libmythtv/grideditcutpoints.h
1 // -*- Mode: c++ -*- 2 #ifndef GRIDEDITCUTPOINTS_H_ 3 #define GRIDEDITCUTPOINTS_H_ 4 5 #include <qstring.h> 6 7 #include "libmyth/mythwidgets.h" 8 #include "uitypes.h" 9 10 #include "grideditimages.h" 11 12 using namespace std; 13 14 class QTimer; 15 class NuppelVideoPlayer; 16 class GridEditImages; 17 18 class MPUBLIC GridEditCutpoints : public MythThemedDialog 19 { 20 Q_OBJECT 21 22 public: 23 // Use this function to instantiate an GridEditCutpoints instance. 24 static void Run(NuppelVideoPlayer *player); 25 26 void refreshImages(); 27 void cacheFramesAreReady(); 28 bool isValid() { return ((usedSubVideoCount > 0) && (m_gridimagemain != NULL)); }; 29 30 protected: 31 GridEditCutpoints(MythMainWindow *parent, 32 NuppelVideoPlayer *player, const char *name = "GridEditCutpoints"); 33 ~GridEditCutpoints(); 34 35 void displayInitialFrame(); 36 37 void handleSelect(); 38 39 void updateStats(bool forcerepaint = false); 40 41 protected slots: 42 void escape(); 43 void updateSlowMotion(); 44 45 private: 46 void keyPressEvent(QKeyEvent *e); 47 48 // seektype == -2 - cutpoint seek 49 // seektype == 1 - normal seek 50 // seektype == 10 - large seek 51 void EditHandleLeft(int seektype = 1); 52 void EditHandleRight(int seektype = 1); 53 void EditHandlePrevCut() { EditHandleLeft(-2); }; 54 void EditHandleNextCut() { EditHandleRight(-2); }; 55 void EditHandleBigJumpRew() { EditHandleLeft(10); }; 56 void EditHandleBigJumpFwd() { EditHandleRight(10); }; 57 void setSlowMotionSpeed(); 58 void refreshCutList(); 59 void refreshSlider(); 60 61 void SetUpdating(bool active, QString text = "Updating"); 62 63 // Private Data 64 65 NuppelVideoPlayer *m_player; 66 GridEditImages *m_images; 67 68 int usedSubVideoCount; 69 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> m_gridimages; 70 // The main Big image 71 UIGridEditImageType* m_gridimagemain; 72 73 long long savedCutpoint; 74 int savedCutType; 75 bool movingCutpoint; 76 77 UITextType *m_framenum; 78 UITextType *m_time; 79 UITextType *m_cutind; 80 UITextType *m_jumpstyle; 81 UITextType *m_updatingind; 82 83 UIGridEditSliderType *m_slider; 84 QTimer *slowMotionTimer; 85 int slowMotionDirection; 86 bool slowMotionActive; 87 bool readyForNextFrame; 88 89 QRect imageScreenArea; 90 }; 91 92 #endif -
mythtv/libs/libmythtv/grideditimages.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditimages.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/grideditimages.cpp
1 #include <qapplication.h> 2 #include <qpainter.h> 3 #include <qfont.h> 4 #include <qsqldatabase.h> 5 #include <qsqlquery.h> 6 #include <math.h> 7 #include <qcursor.h> 8 #include <qapplication.h> 9 #include <qimage.h> 10 #include <qlayout.h> 11 #include <qlabel.h> 12 #include <qdatetime.h> 13 #include <qvgroupbox.h> 14 #include <qheader.h> 15 #include <qrect.h> 16 17 #include <unistd.h> 18 #include <iostream> 19 #include <algorithm> 20 using namespace std; 21 22 #include "mythcontext.h" 23 #include "mythdbcon.h" 24 #include "grideditimages.h" 25 #include "grideditcutpoints.h" 26 #include "NuppelVideoPlayer.h" 27 28 #define FRAME_DEBUG 0 29 #define CACHE_DEBUG 1 30 31 GridEditImages::GridEditImages(GridEditCutpoints *editor, NuppelVideoPlayer *player) 32 { 33 m_editor = editor; 34 m_player = player; 35 usedSubVideoCount = 0; 36 37 lastmovewasright= true; 38 39 int i; 40 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 41 { 42 stillFrames[i] = NULL; 43 stillFramesBig[i] = NULL; 44 cutFrames[i] = 0; 45 } 46 47 memset(cutFramesCache, 0, sizeof(cutFramesCache)); 48 memset(stillFramesCache, 0, sizeof(stillFramesCache)); 49 memset(stillFramesBigCache, 0, sizeof(stillFramesBigCache)); 50 stillFrameCacheCount = 0; 51 stillFramesCacheBase = 0; 52 53 54 // Get first frames... 55 stillMainFrameNumber = m_player->GetFramesPlayed(); 56 if (stillMainFrameNumber <= 0) 57 stillMainFrameNumber = 1; 58 59 // maxFrameNumber may be overridden if neccessary 60 maxFrameNumber = m_player->GetTotalFrameCount(); 61 maxFrameNumberNVP = m_player->GetTotalFrameCount(); 62 63 if (stillMainFrameNumber <= 0) 64 stillMainFrameNumber = 1; 65 66 if (stillMainFrameNumber > maxFrameNumber) 67 stillMainFrameNumber = maxFrameNumber; 68 69 getImagesTimer = new QTimer(this); 70 QObject::connect(getImagesTimer, SIGNAL(timeout()), 71 this, SLOT(updateAllFrames())); 72 73 74 } 75 76 GridEditImages::~GridEditImages() 77 { 78 emptyCache(); 79 clearStillFrames(); 80 m_player->EditSeekToFrame(stillMainFrameNumber); 81 } 82 83 QPixmap *GridEditImages::makeScaledPixmap(const QImage& qim, QSize sz) 84 { 85 QPixmap *retval; 86 if (qim.size() == sz) 87 { 88 retval = new QPixmap(sz); 89 QPainter p(retval); 90 p.drawImage(0, 0, qim); 91 } 92 else 93 { 94 retval = new QPixmap(sz); 95 retval->fill(Qt::black); 96 QPainter p(retval); 97 98 int tl_left = 0; 99 int tl_top = 0; 100 if (sz.width() > qim.width()) 101 tl_left += (sz.width() - qim.width()) / 2; 102 103 if (sz.height() > qim.height()) 104 tl_top += (sz.height() - qim.height()) / 2; 105 106 // VERBOSE(VB_GENERAL, QString("Size mismatch qim(%1, %2) != sz(%3, %4) Shift to (%5, %6)") 107 // .arg(qim.width()).arg(qim.height()) 108 // .arg(sz.width()).arg(sz.height()) 109 // .arg(tl_left).arg(tl_top)); 110 111 p.drawImage(tl_left, tl_top, qim); 112 } 113 return retval; 114 } 115 116 117 void GridEditImages::getMainStillFrame() 118 { 119 getSpecificFrame(0); 120 } 121 122 bool GridEditImages::getFrameIndexes(int newlevel) 123 { 124 // levels: 125 // 0 - onscreen frames 126 // 1 - precache frames 127 // 2 - fill-out-the buffer frames 128 129 if (newlevel > 2) 130 return false; 131 132 // This gets the upper and lower indexes of the frames we need to get. 133 // Note these indexes maybe negative 134 // Negative frames are before the main frame 135 // Frame #0 is the main frame 136 // Positive frames are after the main frame 137 138 // Basic initialization 139 // Doesn't go to absolute end because it slows down seeking 140 // when you go 1 frame left and right 141 frameIndexLeft = stillFrames.minIndex() + 4; 142 frameIndexRight = stillFrames.maxIndex() - 4; 143 getFutureFramesFirst = false; 144 145 if (newlevel == 0) // Current Display only 146 { 147 frameIndexLeft = -usedSubVideoCount; 148 frameIndexRight = usedSubVideoCount; 149 } 150 else 151 { 152 getFutureFramesFirst = lastmovewasright; 153 154 if (newlevel == 1) // PreCache only 155 { 156 // preCacheIndexLeft and Right are indexes for the frames to start and end on 157 frameIndexLeft = preCacheIndexLeft; 158 frameIndexRight = preCacheIndexRight; 159 } 160 } 161 162 // Make sure we don't fall of the front of the file 163 if (stillMainFrameNumber + frameIndexLeft <= 0) 164 frameIndexLeft = -(stillMainFrameNumber-1); 165 166 // ... or the back of the file 167 if (frameIndexRight > (maxFrameNumber - stillMainFrameNumber)) 168 frameIndexRight = (maxFrameNumber - stillMainFrameNumber); 169 170 #if CACHE_DEBUG 171 VERBOSE(VB_GENERAL, QString("Getting frames from %1 to %2 for level %3") 172 .arg(frameIndexLeft).arg(frameIndexRight).arg(newlevel)); 173 #endif 174 return true; 175 } 176 177 bool GridEditImages::getStillFrames(int maxcount) 178 { 179 // returns true if no more frames to get 180 181 // This will fill in all the missing frames in the cache 182 183 long long i; 184 if (getFutureFramesFirst && frameIndexLeft < 0) 185 { 186 // If we're filling out the cache and the last move was to the right 187 // grab future frames first before any past frames 188 for (i = 1; i <= frameIndexRight; i++) 189 if (getSpecificFrame(i)) 190 if (--maxcount == 0) return false; 191 } 192 193 // grab all appropriate frames 194 195 for (i = frameIndexLeft; i <= frameIndexRight; i++) 196 if (getSpecificFrame(i)) 197 if (--maxcount == 0) return false; 198 199 return true; 200 } 201 202 bool GridEditImages::getSpecificFrame(long long i) 203 { 204 // i is the index within the cache of frames 205 206 // If we're outside of the normal boundaries of the buffer, 207 // see if we've precached this frame 208 if (i < stillFrames.minIndex() || i > stillFrames.maxIndex()) 209 { 210 // First extra cached frame 211 if (stillFrameCacheCount == 0) 212 stillFramesCacheBase = stillMainFrameNumber + i; 213 214 int tmpi; 215 for (tmpi = 0; tmpi < stillFrameCacheCount; tmpi++) 216 { 217 long long tmpframe = (stillFramesCacheBase + tmpi); 218 if (tmpframe == stillMainFrameNumber + i) 219 return false; 220 } 221 222 // Check for cache overflow 223 if (stillFrameCacheCount >= MAX_SUB_VIDEOS) 224 { 225 VERBOSE(VB_GENERAL, QString("Cached too many videos. Max = %1").arg(MAX_SUB_VIDEOS)); 226 return false; 227 } 228 229 tmpi = stillFrameCacheCount++; 230 231 #if CACHE_DEBUG 232 VERBOSE(VB_GENERAL, QString("Caching frame %1, (frm# %2, index %3)") 233 .arg(tmpi).arg(stillMainFrameNumber + i) 234 .arg(i)); 235 #endif 236 237 getFrame(i, cutFramesCache[tmpi], stillFramesCache[tmpi], stillFramesBigCache[tmpi]); 238 return true; 239 } 240 else if (!stillFrames[i]) 241 { 242 getFrame(i, cutFrames[i], stillFrames[i], stillFramesBig[i]); 243 return true; 244 } 245 246 return false; 247 } 248 249 void GridEditImages::getFrame(long long i, 250 int &cutFrame, 251 QPixmap * &stillFrame, 252 QPixmap * &stillFrameBig) 253 { 254 // get this frame 255 long long targetFrame = stillMainFrameNumber + i; 256 257 if (!m_player->EditSeekToFrame(targetFrame)) 258 { 259 VERBOSE(VB_GENERAL, QString("Error seeking to Frame[%1] (frame # %2)") 260 .arg(i).arg(targetFrame)); 261 checkMaxFrameCount(); 262 263 stillFrameBig = new QPixmap(videoSizeMain); 264 stillFrameBig->fill(Qt::gray); 265 266 stillFrame = new QPixmap(videoSizeSmall); 267 stillFrame->fill(Qt::gray); 268 } 269 else 270 { 271 cutFrame = m_player->GetCutStatus(targetFrame); 272 QImage normal, small; 273 m_player->GetScreenGrabsOfCurrentFrame(normal, small); 274 275 stillFrameBig = makeScaledPixmap(normal, videoSizeMain); 276 stillFrame = makeScaledPixmap(small, videoSizeSmall); 277 278 #if FRAME_DEBUG 279 VERBOSE(VB_GENERAL, QString("stillFrames[%1] = %2 (%3)") 280 .arg(i) 281 .arg(targetFrame) 282 .arg(cutFrame)); 283 #endif 284 } 285 } 286 287 void GridEditImages::SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall) 288 { 289 usedSubVideoCount = vcount; 290 videoSizeMain = sizeMain; 291 videoSizeSmall = sizeSmall; 292 SetPreCache(1); 293 294 m_player->SetScreenGrabSizes(videoSizeMain, videoSizeSmall); 295 296 // start to grab the current images 297 getMainStillFrame(); 298 startFrameCaching(); 299 } 300 301 void GridEditImages::startFrameCaching() 302 { 303 frameCacheLevel=0; 304 getFrameIndexes(frameCacheLevel); 305 306 getImagesTimer->start(0); 307 } 308 309 void GridEditImages::SetPreCache(long long pccount) 310 { 311 preCacheIndexLeft = pccount - usedSubVideoCount; 312 preCacheIndexRight = pccount + usedSubVideoCount; 313 } 314 315 void GridEditImages::updateAllFrames() 316 { 317 // getStillFrames() returns 'true' on the next call after it's gotten all requested frames 318 319 if (getStillFrames(1)) 320 { 321 // If we've pre-cached the next screen of frames, tell the editor about it 322 if (frameCacheLevel == 1) 323 m_editor->cacheFramesAreReady(); 324 325 frameCacheLevel++; 326 if (getFrameIndexes(frameCacheLevel)) 327 getStillFrames(1); 328 else 329 stopFrameCaching(); 330 } 331 m_editor->refreshImages(); 332 } 333 334 void GridEditImages::clearStillFrames() 335 { 336 int i; 337 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 338 { 339 if (stillFrames[i]) 340 { 341 delete stillFrames[i]; 342 stillFrames[i] = NULL; 343 } 344 if (stillFramesBig[i]) 345 { 346 delete stillFramesBig[i]; 347 stillFramesBig[i] = NULL; 348 } 349 cutFrames[i] = 0; 350 } 351 } 352 353 bool GridEditImages::shiftStillFramesLeft(long long offset) 354 { 355 if (offset > 2 * stillFrames.maxIndex()) 356 { 357 // Dump all cached data and re-get it 358 clearStillFrames(); 359 } 360 else if (offset < 0) 361 { 362 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 363 // Dump all cached data and re-get it 364 clearStillFrames(); 365 offset = 0; 366 } 367 else if (offset != 0) 368 { 369 // Shift backwards in the stream by offset 370 371 // All frames will actually shift to the right. 372 // frame 'n' will become frame 'n+1' 373 // frame stillFrameMinus[1] will become mainframe 374 // frame stillFramePlus[max] will drop off 375 376 // shove extra frames into the excess space above usedSubVideos 377 378 if (offset >= stillMainFrameNumber) 379 offset = (stillMainFrameNumber-1); 380 381 // printStillFrameStats("Before SL"); 382 int i,j; 383 int minIndex = stillFrames.minIndex(); 384 int maxIndex = stillFrames.maxIndex(); 385 for (i = 0; i < offset; i++) 386 { 387 388 if (stillFrames[maxIndex]) 389 { 390 delete stillFrames[maxIndex]; 391 delete stillFramesBig[maxIndex]; 392 } 393 394 for (j = maxIndex; j > minIndex; j--) { 395 stillFrames[j] = stillFrames[j-1]; 396 stillFramesBig[j] = stillFramesBig[j-1]; 397 cutFrames[j] = cutFrames[j-1]; 398 } 399 400 stillFrames[minIndex] = NULL; 401 stillFramesBig[minIndex] = NULL; 402 cutFrames[minIndex] = 0; 403 } 404 405 // printStillFrameStats("After SL"); 406 407 } 408 409 stillMainFrameNumber -= offset; 410 if (stillMainFrameNumber < 1) 411 stillMainFrameNumber = 1; 412 413 emptyCache(); 414 415 return (stillFramesBig[0] != NULL); 416 } 417 418 bool GridEditImages::shiftStillFramesRight(long long offset) 419 { 420 //VERBOSE(VB_GENERAL, QString("Offset = %1").arg(offset)); 421 if (offset > 2 * stillFrames.maxIndex()) 422 { 423 // Dump all cached data and re-get it 424 clearStillFrames(); 425 } 426 else if (offset < 0) 427 { 428 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 429 // Dump all cached data and re-get it 430 clearStillFrames(); 431 offset = 0; 432 } 433 else if (offset != 0) 434 { 435 436 // Shift forwards in the stream by offset 437 438 // All frames will actually shift to the left. 439 // frame 'n' will become frame 'n-1' 440 // frame stillFramePlus[1] will become mainframe 441 // frame stillFrameMinus[max] will drop off 442 443 // shove extra frames into the excess space above usedSubVideos 444 445 if (stillMainFrameNumber + offset > maxFrameNumber) 446 { 447 offset = (maxFrameNumber - stillMainFrameNumber); 448 VERBOSE(VB_GENERAL, QString("new Offset = %1").arg(offset)); 449 } 450 //printStillFrameStats("Before SR"); 451 452 int i,j; 453 int minIndex = stillFrames.minIndex(); 454 int maxIndex = stillFrames.maxIndex(); 455 456 for (i = 0; i < offset; i++) 457 { 458 if (stillFrames[minIndex]) 459 { 460 delete stillFrames[minIndex]; 461 delete stillFramesBig[minIndex]; 462 } 463 464 for (j = minIndex; j < maxIndex; j++) { 465 stillFrames[j] = stillFrames[j+1]; 466 stillFramesBig[j] = stillFramesBig[j+1]; 467 cutFrames[j] = cutFrames[j+1]; 468 } 469 470 stillFrames[maxIndex] = NULL; 471 stillFramesBig[maxIndex] = NULL; 472 cutFrames[maxIndex] = 0; 473 } 474 475 //printStillFrameStats("After SR"); 476 477 } 478 stillMainFrameNumber += offset; 479 if (stillMainFrameNumber > maxFrameNumber ) 480 stillMainFrameNumber = maxFrameNumber; 481 482 emptyCache(); 483 484 return (stillFramesBig[0] != NULL); 485 } 486 487 void GridEditImages::emptyCache() 488 { 489 #if CACHE_DEBUG 490 if (stillFrameCacheCount > 0) 491 { 492 long long minindex = (stillFramesCacheBase - stillMainFrameNumber); 493 long long maxindex = (stillFramesCacheBase+stillFrameCacheCount-1) - stillMainFrameNumber; 494 VERBOSE(VB_GENERAL, QString("emptying %1 frames (%2 - %3) into [%4] - [%5] ") 495 .arg(stillFrameCacheCount) 496 .arg(stillFramesCacheBase) 497 .arg(stillFramesCacheBase+(stillFrameCacheCount-1)) 498 .arg(minindex).arg(maxindex)); 499 } 500 #endif 501 int i; 502 for (i = 0; i < stillFrameCacheCount; i++) 503 { 504 long long tmpframe = stillFramesCacheBase + i; 505 long long frameIndex = tmpframe - stillMainFrameNumber; 506 507 // frameIndex is the index matching stillFramesCache[i] to stillFrames[frameIndex] 508 // If frameIndex is within the stillFrames range, then use this frame 509 // otherwise delete it 510 511 if (frameIndex >= stillFrames.minIndex() && frameIndex <= stillFrames.maxIndex()) 512 { 513 // move cache data into normal arrays. 514 if (stillFrames[frameIndex]) 515 { 516 VERBOSE(VB_GENERAL, QString("Frame %1 index %2 already exists") 517 .arg(tmpframe).arg(frameIndex)); 518 // Can't move it -- the destination exists 519 delete stillFramesCache[i]; 520 delete stillFramesBigCache[i]; 521 } 522 else 523 { 524 cutFrames[frameIndex] = cutFramesCache[i]; 525 stillFrames[frameIndex] = stillFramesCache[i]; 526 stillFramesBig[frameIndex] = stillFramesBigCache[i]; 527 } 528 } 529 else 530 { 531 delete stillFramesCache[i]; 532 delete stillFramesBigCache[i]; 533 } 534 cutFramesCache[i]=0; 535 stillFramesCache[i] = NULL; 536 stillFramesBigCache[i] = NULL; 537 } 538 stillFrameCacheCount = 0; 539 } 540 541 void GridEditImages::printStillFrameStats(QString caption) 542 { 543 int i; 544 // Debug info for frame cache 545 QString foundframes= caption + " Found Frames: "; 546 547 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 548 if (stillFrames[i]) 549 foundframes += QString("%1 ").arg(i); 550 551 VERBOSE(VB_GENERAL, foundframes); 552 } 553 554 void GridEditImages::refreshCutList(UIGridEditImageType* gridimagemain, 555 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages) 556 { 557 int i; 558 559 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 560 { 561 if (stillFrames[i]) 562 { 563 cutFrames[i] = m_player->GetCutStatus(stillMainFrameNumber+i); 564 if (gridimages[i]) 565 gridimages[i]->setCutStatus(cutFrames[i]); 566 } 567 } 568 gridimagemain->setCutStatus(cutFrames[0]); 569 } 570 571 bool GridEditImages::refreshImages(UIGridEditImageType* gridimagemain, 572 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages, 573 bool mainFrameOnly) 574 { 575 // VERBOSE(VB_GENERAL, "Start"); 576 bool alldone = true; 577 if (!stillFramesBig[0]) 578 VERBOSE(VB_GENERAL, QString("Null Big Main frame %1").arg(stillMainFrameNumber)); 579 gridimagemain->setPixmap(stillFramesBig[0], 580 stillMainFrameNumber, 581 cutFrames[0]); 582 583 if (mainFrameOnly && gridimages[0]) 584 gridimages[0]->setPixmap(stillFrames[0], 585 stillMainFrameNumber, 586 cutFrames[0]); 587 588 if (!mainFrameOnly) 589 { 590 int i; 591 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 592 { 593 if (stillFrames[i] == NULL) 594 alldone = false; 595 if (gridimages[i]) 596 gridimages[i]->setPixmap(stillFrames[i], 597 (stillMainFrameNumber + i), 598 cutFrames[i]); 599 } 600 } 601 602 // VERBOSE(VB_GENERAL, "Finish"); 603 return alldone; 604 } 605 606 607 // Back up x frames 608 void GridEditImages::SeekLeft(long long seekamount, bool cutpointseek) 609 { 610 lastmovewasright = false; 611 stopFrameCaching(); 612 613 if (cutpointseek) 614 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, false); 615 616 //VERBOSE(VB_GENERAL, QString("SeekLeft %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 617 618 if (cutpointseek) 619 SetPreCache(-1); 620 else 621 SetPreCache(-seekamount); 622 623 if (!shiftStillFramesLeft(seekamount)) 624 { 625 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 626 // .arg(seekamount)); 627 // Need to grab the main frame 628 629 getMainStillFrame(); 630 } 631 632 startFrameCaching(); 633 } 634 635 void GridEditImages::SeekRight(long long seekamount, bool cutpointseek) 636 { 637 lastmovewasright = true; 638 stopFrameCaching(); 639 640 if (cutpointseek) 641 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, true); 642 643 //VERBOSE(VB_GENERAL, QString("SeekRight %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 644 645 if (cutpointseek) 646 SetPreCache(1); 647 else 648 SetPreCache(seekamount); 649 650 if (!shiftStillFramesRight(seekamount)) 651 { 652 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 653 // .arg(seekamount)); 654 // Need to grab the main frame 655 656 getMainStillFrame(); 657 } 658 659 startFrameCaching(); 660 } 661 662 void GridEditImages::checkMaxFrameCount() 663 { 664 long long tfc = m_player->GetTotalFrameCount(); 665 if (tfc != maxFrameNumberNVP) 666 { 667 VERBOSE(VB_GENERAL, QString("Updating: tfc %1, mfn %2, mfnNVP %3") 668 .arg(tfc).arg(maxFrameNumber).arg(maxFrameNumberNVP)); 669 // Check to see if things changed 670 maxFrameNumber = tfc; 671 maxFrameNumberNVP = tfc; 672 } 673 } 674 675 FrameStats GridEditImages::GetMainFrameStats() 676 { 677 FrameStats result; 678 679 result.frameNumber = stillMainFrameNumber; 680 result.cutInd = cutFrames[0]; 681 result.maxFrameNumber = maxFrameNumber; 682 683 return result; 684 } 685 -
mythtv/libs/libmythtv/grideditimages.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/grideditimages.h release.20115.0305gridedit/mythtv/libs/libmythtv/grideditimages.h
1 // -*- Mode: c++ -*- 2 #ifndef GRIDEDITIMAGES_H_ 3 #define GRIDEDITIMAGES_H_ 4 5 #include <qstring.h> 6 7 #include "libmyth/mythwidgets.h" 8 9 using namespace std; 10 11 class QTimer; 12 class NuppelVideoPlayer; 13 class GridEditCutpoints; 14 15 #define MAX_SUB_VIDEOS 25 16 17 // Simple class to allow array indexing from -MAX_SUB_VIDEOS to +MAX_SUB_VIDEOS 18 template<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 31 class FrameStats 32 { 33 public: 34 long long frameNumber; 35 int cutInd; 36 long long maxFrameNumber; 37 }; 38 39 class MPUBLIC GridEditImages : public QObject 40 { 41 Q_OBJECT 42 43 public: 44 GridEditImages(GridEditCutpoints *er, NuppelVideoPlayer *player); 45 ~GridEditImages(); 46 47 void refreshCutList(UIGridEditImageType* gridimagemain, myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages); 48 49 // return true if anything changed 50 bool refreshImages(UIGridEditImageType* gridimagemain, 51 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages, 52 bool mainFrameOnly); 53 54 void SeekLeft(long long seekamount, bool cutpointseek = false); 55 void SeekRight(long long seekamount, bool cutpointseek = false); 56 57 FrameStats GetMainFrameStats(); 58 long long GetCurrentFrameNumber() const { return stillMainFrameNumber; } 59 long long GetMaxFrameNumber() const { return maxFrameNumber; } 60 61 void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall); 62 63 protected slots: 64 void updateAllFrames(); 65 66 private: 67 // Private functions 68 void clearStillFrames(); 69 void printStillFrameStats(QString caption); 70 void checkMaxFrameCount(); 71 72 // 'newlevel' paramter for getFrameIndexes(): 73 // 0 = get on screen Frames only 74 // 1 = get preCache Frames only 75 // 2 = get any necessary frames 76 // 3 = done 77 bool getFrameIndexes(int newlevel); 78 79 bool getStillFrames(int maxcount = 1000); 80 void getMainStillFrame(); 81 bool getSpecificFrame(long long frameindex); 82 void getFrame(long long i, int &cutFrame, QPixmap* &stillFrame, QPixmap* &stillFrameBig); 83 void emptyCache(); 84 85 // return true if anything changed 86 bool shiftStillFramesLeft(long long offset); 87 bool shiftStillFramesRight(long long offset); 88 void startFrameCaching(); 89 void stopFrameCaching() { getImagesTimer->stop(); }; 90 91 QPixmap *makeScaledPixmap(const QImage& qim, QSize sz); 92 93 void SetPreCache(long long pccount); 94 95 // Private data 96 // These frames are in the cutlist 97 // 0 == not cut 98 // 1 == cut 99 // 2 == cutpoint (cut left) 100 // 3 == cutpoint (cut right) 101 myArray<int, MAX_SUB_VIDEOS> cutFrames; 102 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames; 103 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig; 104 105 // Right and Left are for pre-caching large seek amounts 106 // (i.e. while seeking +5 seconds, they're places to store the previously displayed data) 107 // If there is any overlap, the main arrays hold the pointers 108 109 int cutFramesCache[MAX_SUB_VIDEOS]; 110 QPixmap *stillFramesCache[MAX_SUB_VIDEOS]; 111 QPixmap *stillFramesBigCache[MAX_SUB_VIDEOS]; 112 int stillFrameCacheCount; 113 long long stillFramesCacheBase; // Frame # for index[0] 114 115 QSize videoSizeMain; 116 QSize videoSizeSmall; 117 int usedSubVideoCount; 118 long long preCacheIndexLeft; 119 long long preCacheIndexRight; 120 long long frameIndexLeft; 121 long long frameIndexRight; 122 bool lastmovewasright; 123 bool getFutureFramesFirst; 124 int frameCacheLevel; 125 126 long long stillMainFrameNumber; // frame number for big still picture 127 long long currentFrameNumberNVP; // frame number the NVP should be on 128 long long maxFrameNumber; // max frame number override for NVP 129 long long maxFrameNumberNVP; // Original NVP number 130 131 GridEditCutpoints *m_editor; 132 NuppelVideoPlayer *m_player; 133 134 QTimer *getImagesTimer; 135 136 }; 137 138 #endif -
mythtv/libs/libmythtv/libmythtv.pro
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/libmythtv.pro release.20115.0305gridedit/mythtv/libs/libmythtv/libmythtv.pro
319 319 # Misc. frontend 320 320 HEADERS += guidegrid.h infostructs.h 321 321 HEADERS += progfind.h ttfont.h 322 HEADERS += grideditcutpoints.h grideditimages.h 322 323 SOURCES += guidegrid.cpp infostructs.cpp 323 324 SOURCES += progfind.cpp ttfont.cpp 325 SOURCES += grideditcutpoints.cpp grideditimages.cpp 324 326 325 327 # DSMCC stuff 326 328 HEADERS += dsmcc.h dsmcccache.h -
mythtv/libs/libmythtv/tv_play.cpp
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/tv_play.cpp release.20115.0305gridedit/mythtv/libs/libmythtv/tv_play.cpp
25 25 #include "remoteencoder.h" 26 26 #include "remoteutil.h" 27 27 #include "guidegrid.h" 28 #include "grideditcutpoints.h" 28 29 #include "progfind.h" 29 30 #include "NuppelVideoPlayer.h" 30 31 #include "programinfo.h" … … 440 441 REG_KEY("TV Editing", "BIGJUMPFWD", "Jump forward 10x the normal amount", 441 442 ">,."); 442 443 REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E"); 444 REG_KEY("TV Editing", "SLOWMO", "Slow Motion Play", "Ctrl+P"); 445 REG_KEY("TV Editing", "PAUSE", "Pause", "P"); 443 446 444 447 /* Teletext keys */ 445 448 REG_KEY("Teletext Menu", "NEXTPAGE", "Next Page", "Down"); … … 2606 2609 2607 2610 if (editmode) 2608 2611 { 2612 if (nvp->GetHideEdits()) 2613 return; 2609 2614 if (!nvp->DoKeypress(e)) 2610 2615 editmode = nvp->GetEditMode(); 2611 2616 if (!editmode) … … 5992 5997 qApp->postEvent(myWindow, me); 5993 5998 } 5994 5999 6000 void TV::ShowEditRecordingGrid() 6001 { 6002 // post the request to the main UI thread 6003 // it will be caught in eventFilter and processed as CustomEvent 6004 // this will create the program guide window (widget) 6005 // on the main thread and avoid a deadlock on Win32 6006 6007 VERBOSE(VB_GENERAL, "Starting Grid Edit"); 6008 QString message = QString("START_EDIT"); 6009 MythEvent* me = new MythEvent(message); 6010 qApp->postEvent(myWindow, me); 6011 } 6012 5995 6013 void TV::ChangeVolume(bool up) 5996 6014 { 5997 6015 AudioOutput *aud = nvp->getAudioOutput(); … … 6525 6543 int editType = tokens[1].toInt(); 6526 6544 doEditSchedule(editType); 6527 6545 } 6546 else if (message.left(10) == "START_EDIT") 6547 { 6548 nvp->ShowEditRecordingGrid(); 6549 } 6528 6550 6529 6551 pbinfoLock.lock(); 6530 6552 if (playbackinfo && message.left(14) == "COMMFLAG_START") -
mythtv/libs/libmythtv/tv_play.h
diff -r -u -N -X diff.exclude.noxml -x release.20115.0305base -x release.20115.0305gridedit release.20115.0305base/mythtv/libs/libmythtv/tv_play.h release.20115.0305gridedit/mythtv/libs/libmythtv/tv_play.h
158 158 void setUnderNetworkControl(bool setting) { underNetworkControl = setting; } 159 159 bool IsSameProgram(ProgramInfo *p); 160 160 161 void ShowEditRecordingGrid(); 161 162 void ShowNoRecorderDialog(void); 162 163 void FinishRecording(void); 163 164 void AskAllowRecording(const QStringList&, int, bool, bool);
