Ticket #6322: 137-editgrid.fixes.code.4.patch
File 137-editgrid.fixes.code.4.patch, 92.9 KB (added by , 15 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 framenumber = -1; 5346 } 5347 5348 void UIGridEditImageType::calculateScreenArea() 5349 { 5350 QRect r = area; 5351 r.moveBy(m_parent->GetAreaRect().left(), 5352 m_parent->GetAreaRect().top()); 5353 screen_area = r; 5354 5355 inner_border.setLeft(screen_area.left()+1); 5356 inner_border.setRight(screen_area.right()-1); 5357 inner_border.setTop(screen_area.top()+1); 5358 inner_border.setBottom(screen_area.bottom()-1); 5359 5360 outer_border.setLeft(screen_area.left()-1); 5361 outer_border.setRight(screen_area.right()+1); 5362 outer_border.setTop(screen_area.top()-1); 5363 outer_border.setBottom(screen_area.bottom()+1); 5364 } 5365 5366 void UIGridEditImageType::Draw(QPainter *p, int drawlayer, int context) 5367 { 5368 if (pmap.isNull()) 5369 { 5370 QColor drawcolor = QColor( 0, 0, 0); 5371 p->setBrush(QBrush(Qt::SolidPattern)); 5372 p->setPen(QPen(drawcolor, 2)); 5373 p->drawRect(screen_area); 5374 } 5375 else 5376 { 5377 p->drawPixmap(screen_area, pmap); 5378 5379 p->setBrush(QBrush(Qt::NoBrush)); 5380 p->setPen(QPen(colorSet[cutStatus], 3)); 5381 p->drawRect(inner_border); 5382 if (cutStatus > 0) { 5383 p->drawLine(inner_border.topLeft(), inner_border.bottomRight()); 5384 p->drawLine(inner_border.bottomLeft(), inner_border.topRight()); 5385 } 5386 } 5387 } 5388 5389 void UIGridEditImageType::setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus) 5390 { 5391 // We can get a null new_pmap at the start or end of the video 5392 if (! new_pmap) 5393 { 5394 clearPixmap(); 5395 return; 5396 } 5397 5398 if (frame == framenumber) 5399 { 5400 // No change in pixmap (?) 5401 setCutStatus(new_cutStatus); 5402 return; 5403 } 5404 5405 pmap = *new_pmap; 5406 framenumber = frame; 5407 5408 if (new_cutStatus >= 0 && new_cutStatus <= 3) 5409 cutStatus = new_cutStatus; 5410 else 5411 cutStatus = 0; 5412 5413 refresh(); 5414 } 5415 5416 void UIGridEditImageType::clearPixmap(bool dorefresh) 5417 { 5418 if (! pmap.isNull()) 5419 { 5420 pmap = QPixmap(); 5421 5422 cutStatus = 0; 5423 framenumber = -1; 5424 if (dorefresh) 5425 refresh(); 5426 } 5427 } 5428 5429 void UIGridEditImageType::setCutStatus(int new_cutStatus) 5430 { 5431 if (new_cutStatus == cutStatus) 5432 return; 5433 5434 if (new_cutStatus >= 0 && new_cutStatus <= 3) 5435 cutStatus = new_cutStatus; 5436 else 5437 cutStatus = 0; 5438 5439 refresh(); 5440 } 5441 5442 // ******************************************************************** 5443 5444 UIGridEditSliderType::UIGridEditSliderType(const QString &name) 5445 : UIType(name) 5446 { 5447 m_drawMap = NULL; 5448 m_position=0; 5449 } 5450 5451 void UIGridEditSliderType::calculateScreenArea() 5452 { 5453 QRect r = area; 5454 r.moveBy(m_parent->GetAreaRect().left(), 5455 m_parent->GetAreaRect().top()); 5456 screen_area = r; 5457 5458 if (m_drawMap) 5459 delete [] m_drawMap; 5460 5461 m_drawWidth = area.width(); 5462 m_drawMap = new unsigned char[m_drawWidth]; 5463 for (int i = 0; i < m_drawWidth; i++) 5464 m_drawMap[i] = 0; 5465 } 5466 5467 void UIGridEditSliderType::ClearAll() 5468 { 5469 for (int i = 0; i < m_drawWidth; i++) 5470 m_drawMap[i] = 0; 5471 refresh(); 5472 } 5473 5474 void UIGridEditSliderType::SetRange( 5475 long long fstart, long long fend, long long fcount) 5476 { 5477 if (fcount <= 0) 5478 { 5479 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 5480 .arg(fcount)); 5481 return; 5482 } 5483 if (fstart < 0) 5484 { 5485 VERBOSE(VB_IMPORTANT, QString("Invalid starting frame: %1") 5486 .arg(fstart)); 5487 return; 5488 } 5489 if (fend < 0) 5490 { 5491 VERBOSE(VB_IMPORTANT, QString("Invalid ending frame: %1") 5492 .arg(fend)); 5493 return; 5494 } 5495 5496 if (fstart > fcount) fstart = fcount; 5497 if (fend > fcount) fend = fcount; 5498 5499 int start = (int)((1.0 * fstart * m_drawWidth) / fcount); 5500 int end = (int)((1.0 * fend * m_drawWidth) / fcount); 5501 5502 if (start < 0) 5503 start = 0; 5504 if (start >= m_drawWidth) 5505 start = m_drawWidth - 1; 5506 if (end < 0) 5507 end = 0; 5508 if (end >= m_drawWidth) 5509 end = m_drawWidth - 1; 5510 5511 if (end < start) 5512 { 5513 int tmp = start; 5514 start = end; 5515 end = tmp; 5516 } 5517 5518 for (int i = start; i < end; i++) 5519 if (m_drawMap[i] < 1) 5520 m_drawMap[i] = 1; 5521 5522 // Mark endpoints 5523 m_drawMap[start] = 2; 5524 m_drawMap[end] = 2; 5525 5526 VERBOSE(VB_GENERAL, QString("Range = %1 - %2 (%3 - %4)") 5527 .arg(start).arg(end) 5528 .arg(fstart).arg(fend)); 5529 refresh(); 5530 } 5531 5532 void UIGridEditSliderType::SetPosition( 5533 long long fposition, long long fcount) 5534 { 5535 if (fcount <= 0) 5536 { 5537 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 5538 .arg(fcount)); 5539 return; 5540 } 5541 5542 if (fposition < 0) 5543 { 5544 VERBOSE(VB_IMPORTANT, QString("Invalid position frame: %1") 5545 .arg(fposition)); 5546 return; 5547 } 5548 5549 if (fposition > fcount) fposition = fcount; 5550 5551 int new_position = (int)(1.0 * fposition * m_drawWidth) / fcount; 5552 5553 if (new_position < 0) 5554 new_position = 0; 5555 if (new_position >= m_drawWidth) 5556 new_position = m_drawWidth - 1; 5557 5558 if (new_position != m_position) 5559 { 5560 m_position = new_position; 5561 refresh(); 5562 } 5563 } 5564 5565 void UIGridEditSliderType::Draw(QPainter *p, int drawlayer, int context) 5566 { 5567 // Draw Background 5568 p->setPen(QPen(colorSet[0], 2)); 5569 p->setBrush(colorSet[0]); 5570 p->drawRect(screen_area); 5571 5572 // Draw bars 5573 5574 // VERBOSE(VB_GENERAL, QString("Starting")); 5575 int i = 0; 5576 do { 5577 int start = 0; 5578 int end = 0; 5579 5580 while (i < m_drawWidth && m_drawMap[i] == 0) i++; 5581 if (i == m_drawWidth) break; 5582 start = i; 5583 5584 i++; 5585 5586 5587 while (i < m_drawWidth && m_drawMap[i] == 1) i++; 5588 end = i; 5589 if (end == m_drawWidth) end--; 5590 5591 // If the next map value is not a normal internal cutpoint 5592 // increment i so we handle it properly 5593 if (end+1 < m_drawWidth && m_drawMap[end+1] != 1) 5594 i++; 5595 5596 // start == starting point 5597 // end == endingpoint 5598 { 5599 QRect r = screen_area; 5600 r.setLeft(r.left() + start); 5601 r.setWidth(end - start); 5602 5603 // VERBOSE(VB_GENERAL, QString("Cut from (%1, %2) - (%3, %4)") 5604 // .arg(r.left()).arg(r.top()) 5605 // .arg(r.right()).arg(r.bottom())); 5606 5607 // VERBOSE(VB_GENERAL, QString("start = %1, m_position = %2, end = %3") 5608 // .arg(start) 5609 // .arg(m_position) 5610 // .arg(end)); 5611 5612 if (start <= m_position && m_position <= end) 5613 { 5614 p->setPen(QPen(colorSet[4], 2)); 5615 p->setBrush(colorSet[4]); 5616 } 5617 else 5618 { 5619 p->setPen(QPen(colorSet[1], 2)); 5620 p->setBrush(colorSet[1]); 5621 } 5622 p->drawRect(r); 5623 5624 p->setPen(QPen(colorSet[2], 2)); 5625 p->setBrush(colorSet[2]); 5626 if (m_drawMap[start] == 2) 5627 p->drawLine(r.topLeft(), r.bottomLeft()); 5628 if (m_drawMap[end] == 2) 5629 p->drawLine(r.topRight(), r.bottomRight()); 5630 5631 } 5632 } while (i < m_drawWidth); 5633 5634 // Draw Current Position Mark 5635 5636 QPoint ptop(screen_area.left() + m_position, screen_area.top()); 5637 QPoint pbot(screen_area.left() + m_position, screen_area.bottom()); 5638 5639 p->setPen(QPen(colorSet[3], 2)); 5640 p->setBrush(colorSet[3]); 5641 p->drawLine(ptop, pbot); 5642 } 5643 5644 // ******************************************************************** 5645 5341 5646 UIKeyType::UIKeyType(const QString &name) 5342 5647 : UIType(name) 5343 5648 { -
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 1406 virtual void Draw(QPainter *, int, int); 1407 void setPixmap(QPixmap *new_pmap, long long frame, int new_cutStatus); 1408 1409 void clearPixmap(bool dorefresh=true); 1410 void setCutStatus(int new_cutStatus); 1411 1412 QRect getOuterBorder() { return outer_border; }; 1413 protected: 1414 1415 QRect area; 1416 QRect inner_border; 1417 QRect outer_border; 1418 QPixmap pmap; 1419 long long framenumber; // for consistency checking 1420 int cutStatus; 1421 QColor colorSet[4]; 1422 }; 1423 1424 class MPUBLIC UIGridEditSliderType : public UIType 1425 { 1426 Q_OBJECT 1427 1428 public: 1429 1430 UIGridEditSliderType(const QString &name); 1431 void calculateScreenArea(); 1432 void setArea(QRect an_area) { area = an_area; }; 1433 1434 void setFillColor(QColor c) { colorSet[0] = c; }; 1435 void setCutColor(QColor c) { colorSet[1] = c; }; 1436 void setCutPointColor(QColor c) { colorSet[2] = c; }; 1437 void setPositionColor(QColor c) { colorSet[3] = c; }; 1438 void setInCutColor(QColor c) { colorSet[4] = c; }; 1439 1440 void ClearAll(); 1441 void SetRange(long long fstart, long long fend, long long fcount); 1442 void SetPosition(long long fposition, long long fcount); 1443 1444 virtual void Draw(QPainter *, int, int); 1445 protected: 1446 1447 QRect area; 1448 unsigned char *m_drawMap; 1449 int m_drawWidth; 1450 int m_position; 1451 1452 QColor colorSet[5]; 1453 }; 1454 1455 1388 1456 class MPUBLIC UIKeyType : public UIType 1389 1457 { 1390 1458 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 bool haveOutlineColor = false; 3468 bool haveCutColor = false; 3469 bool haveCutPointColor = false; 3470 3471 QString name = element.attribute("name", ""); 3472 if (name.isNull() || name.isEmpty()) 3473 { 3474 VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditImage needs a name"); 3475 return; 3476 } 3477 3478 for (QDomNode child = element.firstChild(); !child.isNull(); 3479 child = child.nextSibling()) 3480 { 3481 QDomElement info = child.toElement(); 3482 if (!info.isNull()) 3483 { 3484 if (info.tagName() == "area") 3485 { 3486 area = parseRect(getFirstText(info)); 3487 normalizeRect(area); 3488 } 3489 else if (info.tagName() == "outlinecolor") 3490 { 3491 haveOutlineColor = true; 3492 outlineColor = getFirstText(info); 3493 } 3494 else if (info.tagName() == "cutcolor") 3495 { 3496 haveCutColor = true; 3497 cutColor = getFirstText(info); 3498 } 3499 else if (info.tagName() == "cutpointcolor") 3500 { 3501 haveCutPointColor = true; 3502 cutPointColor = getFirstText(info); 3503 } 3504 else 3505 { 3506 VERBOSE(VB_IMPORTANT, LOC_WARN + 3507 QString("Unknown tag '%1' in grideditimage '%2'") 3508 .arg(info.tagName()).arg(name)); 3509 return; 3510 } 3511 } 3512 } 3513 3514 if (!haveOutlineColor) 3515 { 3516 VERBOSE(VB_IMPORTANT, LOC_WARN + 3517 QString("Missing tag 'outlinecolor' in grideditimage '%1'") 3518 .arg(name)); 3519 return; 3520 } 3521 3522 if (!haveCutColor) 3523 { 3524 VERBOSE(VB_IMPORTANT, LOC_WARN + 3525 QString("Missing tag 'cutcolor' in grideditimage '%1'") 3526 .arg(name)); 3527 return; 3528 } 3529 3530 if (!haveCutPointColor) 3531 { 3532 VERBOSE(VB_IMPORTANT, LOC_WARN + 3533 QString("Missing tag 'cutpointcolor' in grideditimage '%1'") 3534 .arg(name)); 3535 return; 3536 } 3537 3538 UIGridEditImageType *gei = new UIGridEditImageType(name); 3539 gei->SetScreen(wmult, hmult); 3540 gei->setArea(area); 3541 gei->setOutlineColor(outlineColor); 3542 gei->setCutColor(cutColor); 3543 gei->setCutPointColor(cutPointColor); 3544 gei->SetParent(container); 3545 gei->calculateScreenArea(); 3546 gei->clearPixmap(false); 3547 container->AddType(gei); 3548 } 3549 3550 void XMLParse::parseGridEditSlider(LayerSet *container, QDomElement &element) 3551 { 3552 QRect area; 3553 QColor fillColor; 3554 QColor cutColor; 3555 QColor inCutColor; 3556 QColor cutPointColor; 3557 QColor positionColor; 3558 bool haveFillColor = false; 3559 bool haveCutColor = false; 3560 bool haveInCutColor = false; 3561 bool haveCutPointColor = false; 3562 bool havePositionColor = false; 3563 3564 QString name = element.attribute("name", ""); 3565 if (name.isNull() || name.isEmpty()) 3566 { 3567 VERBOSE(VB_IMPORTANT, LOC_WARN + "GridEditSlider needs a name"); 3568 return; 3569 } 3570 3571 for (QDomNode child = element.firstChild(); !child.isNull(); 3572 child = child.nextSibling()) 3573 { 3574 QDomElement info = child.toElement(); 3575 if (!info.isNull()) 3576 { 3577 if (info.tagName() == "area") 3578 { 3579 area = parseRect(getFirstText(info)); 3580 normalizeRect(area); 3581 } 3582 else if (info.tagName() == "fillcolor") 3583 { 3584 haveFillColor = true; 3585 fillColor = getFirstText(info); 3586 } 3587 else if (info.tagName() == "cutcolor") 3588 { 3589 haveCutColor = true; 3590 cutColor = getFirstText(info); 3591 } 3592 else if (info.tagName() == "incutcolor") 3593 { 3594 haveInCutColor = true; 3595 inCutColor = getFirstText(info); 3596 } 3597 else if (info.tagName() == "cutpointcolor") 3598 { 3599 haveCutPointColor = true; 3600 cutPointColor = getFirstText(info); 3601 } 3602 else if (info.tagName() == "positioncolor") 3603 { 3604 havePositionColor = true; 3605 positionColor = getFirstText(info); 3606 } 3607 else 3608 { 3609 VERBOSE(VB_IMPORTANT, LOC_WARN + 3610 QString("Unknown tag '%1' in grideditslider '%2'") 3611 .arg(info.tagName()).arg(name)); 3612 return; 3613 } 3614 } 3615 } 3616 3617 if (!haveFillColor) 3618 { 3619 VERBOSE(VB_IMPORTANT, LOC_WARN + 3620 QString("Missing tag 'fillcolor' in grideditslider '%1'") 3621 .arg(name)); 3622 return; 3623 } 3624 3625 if (!haveCutColor) 3626 { 3627 VERBOSE(VB_IMPORTANT, LOC_WARN + 3628 QString("Missing tag 'cutcolor' in grideditslider '%1'") 3629 .arg(name)); 3630 return; 3631 } 3632 3633 if (!haveInCutColor) 3634 { 3635 VERBOSE(VB_IMPORTANT, LOC_WARN + 3636 QString("Missing tag 'incutcolor' in grideditslider '%1'") 3637 .arg(name)); 3638 return; 3639 } 3640 3641 if (!haveCutPointColor) 3642 { 3643 VERBOSE(VB_IMPORTANT, LOC_WARN + 3644 QString("Missing tag 'cutpointcolor' in grideditslider '%1'") 3645 .arg(name)); 3646 return; 3647 } 3648 3649 if (!havePositionColor) 3650 { 3651 VERBOSE(VB_IMPORTANT, LOC_WARN + 3652 QString("Missing tag 'positioncolor' in grideditslider '%1'") 3653 .arg(name)); 3654 return; 3655 } 3656 3657 UIGridEditSliderType *ges = new UIGridEditSliderType(name); 3658 ges->SetScreen(wmult, hmult); 3659 ges->setArea(area); 3660 ges->setFillColor(fillColor); 3661 ges->setCutColor(cutColor); 3662 ges->setInCutColor(inCutColor); 3663 ges->setCutPointColor(cutPointColor); 3664 ges->setPositionColor(positionColor); 3665 ges->SetParent(container); 3666 ges->calculateScreenArea(); 3667 container->AddType(ges); 3668 } 3669 3448 3670 void XMLParse::parseListBtnArea(LayerSet *container, QDomElement &element) 3449 3671 { 3450 3672 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_buffer(NULL), grid_edit_image_buffer_length(0), 221 228 // Filters 222 229 videoFiltersForProgram(""), videoFiltersOverride(""), 223 230 postfilt_width(0), postfilt_height(0), … … 388 395 output_jmeter = NULL; 389 396 } 390 397 398 if (grid_edit_image_buffer) 399 { 400 delete [] grid_edit_image_buffer; 401 grid_edit_image_buffer = NULL; 402 grid_edit_image_buffer_length=0; 403 } 404 391 405 ShutdownYUVResize(); 392 406 } 393 407 … … 1526 1540 return retval; 1527 1541 } 1528 1542 1543 1544 QImage NuppelVideoPlayer::GetScreenGrabOfCurrentFrame(QSize size) 1545 { 1546 1547 unsigned char *data = NULL; 1548 VideoFrame *frame = NULL; 1549 AVPicture orig; 1550 AVPicture retbuf; 1551 bzero(&orig, sizeof(AVPicture)); 1552 bzero(&retbuf, sizeof(AVPicture)); 1553 1554 QImage edit_scaled_img; 1555 int vw, vh; 1556 if (!(frame = GetCurrentFrame(vw, vh))) 1557 { 1558 return edit_scaled_img; 1559 } 1560 1561 if (!(data = frame->buf)) 1562 { 1563 ReleaseCurrentFrame(frame); 1564 return edit_scaled_img; 1565 } 1566 1567 avpicture_fill(&orig, data, PIX_FMT_YUV420P, 1568 video_dim.width(), video_dim.height()); 1569 1570 avpicture_deinterlace(&orig, &orig, PIX_FMT_YUV420P, 1571 video_dim.width(), video_dim.height()); 1572 1573 int bufflen = video_dim.width() * video_dim.height() * 4; 1574 if (!grid_edit_image_buffer) 1575 { 1576 grid_edit_image_buffer = new unsigned char[bufflen]; 1577 grid_edit_image_buffer_length = bufflen; 1578 } 1579 else if (bufflen > grid_edit_image_buffer_length) 1580 { 1581 delete [] grid_edit_image_buffer; 1582 grid_edit_image_buffer = new unsigned char[bufflen]; 1583 grid_edit_image_buffer_length = bufflen; 1584 } 1585 1586 // Connect outputbuf to retbuf 1587 avpicture_fill(&retbuf, grid_edit_image_buffer, PIX_FMT_RGBA32, 1588 video_dim.width(), video_dim.height()); 1589 1590 // convert from orig into retbuf(grid_edit_image_buffer) 1591 img_convert(&retbuf, PIX_FMT_RGBA32, &orig, PIX_FMT_YUV420P, 1592 video_dim.width(), video_dim.height()); 1593 1594 QImage tmpimage = QImage(grid_edit_image_buffer, video_dim.width(), video_dim.height(), 1595 32, NULL, 65536 * 65536, QImage::LittleEndian); 1596 1597 ReleaseCurrentFrame(frame); 1598 1599 #ifdef MMX 1600 edit_scaled_img = tmpimage.scale(size, QImage::ScaleMin).swapRGB(); 1601 #else 1602 edit_scaled_img = tmpimage.scale(size, QImage::ScaleMin); 1603 #endif 1604 1605 return edit_scaled_img; 1606 } 1607 1529 1608 void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame) 1530 1609 { 1531 1610 if (frame) … … 4989 5068 4990 5069 dialogname = ""; 4991 5070 5071 osd->HideAllExcept("editmode"); 5072 4992 5073 QMap<QString, QString> infoMap; 4993 5074 m_playbackinfo->ToMap(infoMap); 4994 5075 osd->SetText("editmode", infoMap, -1); … … 5044 5125 m_playbackinfo->SetEditing(false); 5045 5126 } 5046 5127 5128 bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame) 5129 { 5130 bool tmpexactseeks = exactseeks; 5131 GetDecoder()->setExactSeeks(true); 5132 5133 // VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2") 5134 // .arg(GetFramesPlayed()) 5135 // .arg(targetFrame)); 5136 5137 if (framesPlayed > targetFrame) 5138 { 5139 // seek back 5140 rewindtime = framesPlayed - targetFrame; 5141 while (rewindtime != 0) 5142 usleep(1000); 5143 } 5144 else 5145 { 5146 // seek forward 5147 fftime = targetFrame - framesPlayed; 5148 while (fftime != 0) 5149 usleep(1000); 5150 5151 } 5152 // VERBOSE(VB_GENERAL, QString("After current frame = %1") 5153 // .arg(GetFramesPlayed())); 5154 GetDecoder()->setExactSeeks(tmpexactseeks); 5155 return (targetFrame == framesPlayed); 5156 } 5157 5158 void NuppelVideoPlayer::EditHandleClearMap() 5159 { 5160 QMap<long long, int>::Iterator it; 5161 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5162 osd->HideEditArrow(it.key(), it.data()); 5163 5164 deleteMap.clear(); 5165 UpdateEditSlider(); 5166 } 5167 5168 void NuppelVideoPlayer::EditHandleInvertMap() 5169 { 5170 QMap<long long, int>::Iterator it; 5171 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5172 ReverseMark(it.key()); 5173 5174 UpdateEditSlider(); 5175 UpdateTimeDisplay(); 5176 } 5177 5178 void NuppelVideoPlayer::EditHandleLoadCommSkip() 5179 { 5180 if (hascommbreaktable) 5181 { 5182 commBreakMapLock.lock(); 5183 QMap<long long, int>::Iterator it; 5184 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5185 { 5186 if (!deleteMap.contains(it.key())) 5187 { 5188 if (it.data() == MARK_COMM_START) 5189 AddMark(it.key(), MARK_CUT_START); 5190 else 5191 AddMark(it.key(), MARK_CUT_END); 5192 } 5193 } 5194 commBreakMapLock.unlock(); 5195 UpdateEditSlider(); 5196 UpdateTimeDisplay(); 5197 } 5198 } 5199 5047 5200 bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e) 5048 5201 { 5049 5202 bool handled = false; … … 5123 5276 UpdateTimeDisplay(); 5124 5277 } 5125 5278 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 } 5279 EditHandleClearMap(); 5134 5280 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 } 5281 EditHandleInvertMap(); 5143 5282 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 } 5283 EditHandleLoadCommSkip(); 5164 5284 else if (action == "PREVCUT") 5165 5285 { 5166 5286 int old_seekamount = seekamount; … … 5206 5326 UpdateEditSlider(); 5207 5327 UpdateTimeDisplay(); 5208 5328 } 5209 else if (action == "ESCAPE" || action == "MENU" || 5210 action == "TOGGLEEDIT") 5329 else if (action == "TOGGLEEDIT" || action == "MENU") 5330 m_tv->ShowEditRecordingGrid(); 5331 else if (action == "ESCAPE") 5211 5332 { 5212 5333 DisableEdit(); 5213 5334 retval = false; … … 5220 5341 return retval; 5221 5342 } 5222 5343 5344 void NuppelVideoPlayer::ShowEditRecordingGrid(void) 5345 { 5346 // Completely hide the OSD 5347 osd->HideAll(); 5348 hideedits = true; 5349 5350 GridEditCutpoints::Run(this); 5351 5352 if (grid_edit_image_buffer) 5353 { 5354 delete [] grid_edit_image_buffer; 5355 grid_edit_image_buffer = NULL; 5356 grid_edit_image_buffer_length = 0; 5357 } 5358 5359 allow_pagesize = false; 5360 hideedits = false; 5361 5362 // Show OSD 5363 5364 QMap<QString, QString> infoMap; 5365 m_playbackinfo->ToMap(infoMap); 5366 osd->SetText("editmode", infoMap, -1); 5367 5368 UpdateEditSlider(); 5369 UpdateTimeDisplay(); 5370 if (seekamountpos == 3 || seekamountpos == 4) 5371 UpdateSeekAmount(true); 5372 else 5373 UpdateSeekAmountDisplay(); 5374 5375 QMap<long long, int>::Iterator it; 5376 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5377 AddMark(it.key(), it.data()); 5378 } 5379 5223 5380 AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const 5224 5381 { 5225 5382 if (videoOutput) … … 5311 5468 5312 5469 void NuppelVideoPlayer::UpdateSeekAmount(bool up) 5313 5470 { 5314 if (seekamountpos > 0 && !up) 5315 seekamountpos--; 5316 if (seekamountpos < 9 && up) 5317 seekamountpos++; 5471 if (up) 5472 { 5473 if (seekamountpos < 11) 5474 seekamountpos++; 5475 if (allow_pagesize) 5476 { 5477 if (seekamountpos == 1) 5478 seekamountpos = 2; 5479 } 5480 else 5481 { 5482 if (seekamountpos == 3 || seekamountpos == 4) 5483 seekamountpos = 5; 5484 } 5485 } 5486 else 5487 { 5488 if (seekamountpos > 0) 5489 seekamountpos--; 5490 if (allow_pagesize) 5491 { 5492 if (seekamountpos == 1) 5493 seekamountpos =0; 5494 } 5495 else 5496 { 5497 if (seekamountpos == 3 || seekamountpos == 4) 5498 seekamountpos = 2; 5499 } 5500 } 5318 5501 5319 QString text = "";5502 QString text; 5320 5503 5321 5504 switch (seekamountpos) 5322 5505 { 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; 5506 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5507 5508 // Only for non-edit grid 5509 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5510 // Only for non-edit grid 5511 5512 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5513 5514 // Case 3 & 4 are for the edit grid only 5515 case 3: text = QObject::tr("1/2 Page"); seekamount = half_page; break; 5516 case 4: text = QObject::tr("Full Page"); seekamount = 2*half_page; break; 5517 // Case 3 & 4 are for the edit grid only 5518 5519 case 5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5520 case 6: text = QObject::tr("1 second"); seekamount = (int)roundf(video_frame_rate); break; 5521 case 7: text = QObject::tr("5 seconds"); seekamount = (int)roundf(video_frame_rate * 5); break; 5522 case 8: text = QObject::tr("20 seconds"); seekamount = (int)roundf(video_frame_rate * 20); break; 5523 case 9: text = QObject::tr("1 minute"); seekamount = (int)roundf(video_frame_rate * 60); break; 5524 case 10: text = QObject::tr("5 minutes"); seekamount = (int)roundf(video_frame_rate * 300); break; 5525 case 11: text = QObject::tr("10 minutes"); seekamount = (int)roundf(video_frame_rate * 600); break; 5526 default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break; 5334 5527 } 5335 5528 5529 seekamounttext = text; 5530 UpdateSeekAmountDisplay(); 5531 } 5532 5533 void NuppelVideoPlayer::UpdateSeekAmountDisplay(void) 5534 { 5336 5535 QMap<QString, QString> infoMap; 5337 infoMap["seekamount"] = text; 5338 osd->SetText("editmode", infoMap, -1); 5536 infoMap["seekamount"] = seekamounttext; 5537 if (!hideedits) 5538 osd->SetText("editmode", infoMap, -1); 5339 5539 } 5340 5540 5341 5541 void NuppelVideoPlayer::UpdateTimeDisplay(void) … … 5365 5565 infoMap["timedisplay"] = timestr; 5366 5566 infoMap["framedisplay"] = framestr; 5367 5567 infoMap["cutindicator"] = cutmarker; 5368 osd->SetText("editmode", infoMap, -1); 5568 if (!hideedits) 5569 osd->SetText("editmode", infoMap, -1); 5369 5570 } 5370 5571 5371 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)5572 DeletePointInfo NuppelVideoPlayer::GetDeletePointInfo(long long frame, bool allowSelectNear) 5372 5573 { 5373 bool deletepoint = false; 5374 bool cut_after = false; 5375 int direction = 0; 5574 DeletePointInfo retval; 5376 5575 5377 5576 if(!deleteMap.isEmpty()) 5378 5577 { 5379 5578 QMap<long long, int>::ConstIterator iter = deleteMap.begin(); 5380 5579 5381 while((iter != deleteMap.end()) && (iter.key() < frame sPlayed))5580 while((iter != deleteMap.end()) && (iter.key() < frame)) 5382 5581 ++iter; 5383 5582 5384 5583 if (iter == deleteMap.end()) 5385 5584 { 5386 5585 --iter; 5387 cut_after = !iter.data();5586 retval.cut_after = !iter.data(); 5388 5587 } 5389 else if((iter != deleteMap.begin()) && (iter.key() != frame sPlayed))5588 else if((iter != deleteMap.begin()) && (iter.key() != frame)) 5390 5589 { 5391 5590 long long value = iter.key(); 5392 if((frame sPlayed - (--iter).key()) > (value - framesPlayed))5591 if((frame - (--iter).key()) > (value - frame)) 5393 5592 { 5394 cut_after = !iter.data();5593 retval.cut_after = !iter.data(); 5395 5594 ++iter; 5396 5595 } 5397 5596 else 5398 cut_after = !iter.data();5597 retval.cut_after = !iter.data(); 5399 5598 } 5400 5599 5401 direction = iter.data();5402 deleteframe = iter.key();5600 retval.direction = iter.data(); 5601 retval.deleteframe = iter.key(); 5403 5602 5404 if ((absLongLong( deleteframe - framesPlayed) <5603 if ((absLongLong(retval.deleteframe - frame) < 5405 5604 (int)ceil(20 * video_frame_rate)) && !allowSelectNear) 5406 5605 { 5407 deletepoint = true;5606 retval.deletepoint = true; 5408 5607 } 5409 5608 } 5609 return retval; 5610 } 5611 5612 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear) 5613 { 5614 DeletePointInfo dpi = GetDeletePointInfo(framesPlayed, allowSelectNear); 5615 deleteframe = dpi.deleteframe; 5410 5616 5411 if (d eletepoint)5617 if (dpi.deletepoint) 5412 5618 { 5413 5619 QString message = QObject::tr("You are close to an existing cut point. " 5414 5620 "Would you like to:"); … … 5416 5622 QString option2 = QObject::tr("Move this cut point to the current " 5417 5623 "position"); 5418 5624 QString option3 = QObject::tr("Flip directions - delete to the "); 5419 if (d irection == 0)5625 if (dpi.direction == 0) 5420 5626 option3 += QObject::tr("right"); 5421 5627 else 5422 5628 option3 += QObject::tr("left"); … … 5446 5652 options += option1; 5447 5653 options += option2; 5448 5654 5449 osd->NewDialogBox(dialogname, message, options, -1, cut_after);5655 osd->NewDialogBox(dialogname, message, options, -1, dpi.cut_after); 5450 5656 } 5451 5657 } 5452 5658 … … 5497 5703 5498 5704 void NuppelVideoPlayer::UpdateEditSlider(void) 5499 5705 { 5500 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5706 if (!hideedits) 5707 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5501 5708 } 5502 5709 5503 5710 void NuppelVideoPlayer::AddMark(long long frames, int type) 5504 5711 { 5505 5712 deleteMap[frames] = type; 5506 osd->ShowEditArrow(frames, totalFrames, type); 5713 if (!hideedits) 5714 osd->ShowEditArrow(frames, totalFrames, type); 5507 5715 } 5508 5716 5509 5717 void NuppelVideoPlayer::DeleteMark(long long frames) 5510 5718 { 5511 osd->HideEditArrow(frames, deleteMap[frames]); 5719 if (!hideedits) 5720 osd->HideEditArrow(frames, deleteMap[frames]); 5512 5721 deleteMap.remove(frames); 5513 5722 } 5514 5723 5515 5724 void NuppelVideoPlayer::ReverseMark(long long frames) 5516 5725 { 5517 osd->HideEditArrow(frames, deleteMap[frames]); 5726 if (!hideedits) 5727 osd->HideEditArrow(frames, deleteMap[frames]); 5518 5728 5519 5729 if (deleteMap[frames] == MARK_CUT_END) 5520 5730 deleteMap[frames] = MARK_CUT_START; 5521 5731 else 5522 5732 deleteMap[frames] = MARK_CUT_END; 5523 5733 5524 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5734 if (!hideedits) 5735 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5736 } 5737 5738 long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right) 5739 { 5740 QMap<long long, int>::Iterator i = deleteMap.begin(); 5741 long long framenum = -1; 5742 long long seekcount = 0; 5743 if (right) 5744 { 5745 for (; i != deleteMap.end(); ++i) 5746 { 5747 if (i.key() > baseframe) 5748 { 5749 framenum = i.key(); 5750 break; 5751 } 5752 } 5753 if (framenum == -1) 5754 framenum = totalFrames; 5755 seekcount = framenum - baseframe; 5756 } 5757 else 5758 { 5759 for (; i != deleteMap.end(); ++i) 5760 { 5761 if (i.key() >= baseframe) 5762 break; 5763 framenum = i.key(); 5764 } 5765 if (framenum == -1) 5766 framenum = 0; 5767 seekcount = baseframe - framenum; 5768 } 5769 return seekcount; 5525 5770 } 5526 5771 5527 5772 void NuppelVideoPlayer::HandleArbSeek(bool right) 5528 5773 { 5529 5774 if (seekamount == -2) 5530 5775 { 5531 QMap<long long, int>::Iterator i = deleteMap.begin(); 5532 long long framenum = -1; 5776 long long seekcount = CalcCutPointSeek(framesPlayed, right); 5533 5777 if (right) 5534 5778 { 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; 5779 fftime = seekcount; 5547 5780 while (fftime > 0) 5548 5781 usleep(1000); 5549 5782 } 5550 5783 else 5551 5784 { 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; 5785 rewindtime = seekcount; 5562 5786 while (rewindtime > 0) 5563 5787 usleep(1000); 5564 5788 } … … 5589 5813 UpdateEditSlider(); 5590 5814 } 5591 5815 5816 int NuppelVideoPlayer::GetCutStatus(long long testframe) const 5817 { 5818 int retval = 0; 5819 QMap<long long, int>::const_iterator i; 5820 i = deleteMap.find(testframe); 5821 if (i == deleteMap.end()) { 5822 // testframe is not an explicit cutpoint 5823 // See if it is in a deleted area 5824 if (IsInDelete(testframe)) 5825 retval = 1; 5826 } else { 5827 int direction = i.data(); 5828 if (direction == 0) 5829 retval = 2; 5830 else 5831 retval = 3; 5832 } 5833 5834 return retval; 5835 } 5836 5592 5837 bool NuppelVideoPlayer::IsInDelete(long long testframe) const 5593 5838 { 5594 5839 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 QImage GetScreenGrabOfCurrentFrame(QSize size); // Get current frame 310 311 void EditHandleClearMap(); 312 void EditHandleInvertMap(); 313 void EditHandleLoadCommSkip(); 314 315 void ShowEditRecordingGrid(); 316 292 317 // Reinit 293 318 void ReinitOSD(void); 294 319 void ReinitVideo(void); … … 406 431 hidedvdbutton = hide; 407 432 } 408 433 434 // Stuf for GridEditCutpoints 435 long long CalcCutPointSeek(long long baseframe, bool right); 436 // returns 437 // 0 - no cut 438 // 1 - is deleted 439 // 2 - cut left 440 // 3 - cut right 441 int GetCutStatus(long long testframe) const; 442 long long GetSeekAmount() { return seekamount; } 443 QString GetSeekAmountText() { return seekamounttext; } 444 409 445 protected: 410 446 void DisplayPauseFrame(void); 411 447 void DisplayNormalFrame(void); … … 487 523 void HandleSelect(bool allowSelectNear = false); 488 524 void HandleResponse(void); 489 525 526 DeletePointInfo GetDeletePointInfo(long long frame, bool allowSelectNear); 527 528 490 529 void UpdateTimeDisplay(void); 530 int GetSeekAmountPos() { return seekamountpos; } 491 531 void UpdateSeekAmount(bool up); 532 void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; } 533 void UpdateSeekAmountDisplay(void); 492 534 void UpdateEditSlider(void); 493 535 494 536 // Private A/V Sync Stuff … … 560 602 bool livetv; 561 603 bool watchingrecording; 562 604 bool editmode; 605 bool hideedits; 563 606 bool resetvideo; 564 607 bool using_null_videoout; 565 608 bool no_audio_in; … … 579 622 long long fftime; 580 623 /// 1..9 == keyframe..10 minutes. 0 == cut point 581 624 int seekamountpos; 625 /// Used for Grid Edit logic 626 bool allow_pagesize; 627 int half_page; 582 628 /// Seekable frame increment when not using exact seeks. 583 629 /// Usually equal to keyframedist. 584 630 int seekamount; 631 QString seekamounttext; // OSD seek units 585 632 /// Iff true we ignore seek amount and try to seek to an 586 633 /// exact frame ignoring key frame restrictions. 587 634 bool exactseeks; … … 714 761 QMutex yuv_lock; 715 762 QWaitCondition yuv_wait; 716 763 764 // EditGrid still image capture 765 unsigned char *grid_edit_image_buffer; 766 int grid_edit_image_buffer_length; 767 717 768 // Filters 718 769 QMutex videofiltersLock; 719 770 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 er->Show(); 37 er->displayInitialFrame(); 38 er->exec(); 39 40 delete er; 41 42 gContext->removeCurrentLocation(); 43 VERBOSE(VB_GENERAL, "Ending"); 44 } 45 46 GridEditCutpoints::GridEditCutpoints(MythMainWindow *parent, 47 NuppelVideoPlayer *player, const char *name) 48 : MythThemedDialog(parent, "grideditcutpoints", "", name) 49 { 50 m_player = player; 51 m_images = new GridEditImages(this, player); 52 53 int i; 54 for (i = m_gridimages.minIndex(); i < m_gridimages.maxIndex(); i++) 55 { 56 m_gridimages[i] = NULL; 57 } 58 59 usedSubVideoCount=0; 60 61 QSize videoSizeMain, videoSizeSmall; 62 63 m_gridimages[0] = getUIGridEditImageType("mainvideo"); 64 if (m_gridimages[0]) 65 videoSizeMain = m_gridimages[0]->getScreenArea().size(); 66 else 67 VERBOSE(VB_IMPORTANT, "FATAL: Couldn't find mainedit:mainvideo"); 68 69 for (i = 1; i < m_gridimages.maxIndex(); i++) 70 { 71 QString p = QString("videop%1").arg(i); 72 QString m = QString("videom%1").arg(i); 73 74 // Minus frame i 75 m_gridimages[-i] = getUIGridEditImageType(m); 76 if (m_gridimages[-i]) 77 { 78 QSize tmpVideoSizeSmall = m_gridimages[-i]->getScreenArea().size(); 79 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 80 VERBOSE(VB_IMPORTANT, 81 QString("Multiple sizes found for edit videos (%1)").arg(m)); 82 else 83 videoSizeSmall = tmpVideoSizeSmall; 84 if (i > usedSubVideoCount) usedSubVideoCount=i; 85 } 86 87 m_gridimages[i] = getUIGridEditImageType(p); 88 if (m_gridimages[i]) 89 { 90 QSize tmpVideoSizeSmall = m_gridimages[i]->getScreenArea().size(); 91 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 92 VERBOSE(VB_IMPORTANT, 93 QString("Multiple sizes found for edit videos (%1)").arg(p)); 94 else 95 videoSizeSmall = tmpVideoSizeSmall; 96 if (i > usedSubVideoCount) usedSubVideoCount=i; 97 } 98 } 99 m_images->SetVideoInfo(usedSubVideoCount, videoSizeMain, videoSizeSmall); 100 101 m_player->SetHalfPageSize(usedSubVideoCount); 102 m_slider = getUIGridEditSliderType("positionbar"); 103 if (!m_slider) 104 VERBOSE(VB_GENERAL, "Missing positionbar for GridEditCutpoints"); 105 106 // Get Status boxes 107 { 108 m_framenum = getUITextType("framenum"); 109 m_time = getUITextType("time"); 110 m_cutind = getUITextType("cutind"); 111 m_jumpstyle = getUITextType("jumpstyle"); 112 m_updatingind = getUITextType("updatingind"); 113 } 114 115 VERBOSE(VB_GENERAL, QString("main = (%1, %2) small = (%3, %4)") 116 .arg(videoSizeMain.width()).arg(videoSizeMain.height()) 117 .arg(videoSizeSmall.width()).arg(videoSizeSmall.height())); 118 119 slowMotionDirection = 1; // start off play forward 120 slowMotionActive = false; 121 readyForNextFrame = false; 122 slowMotionTimer = new QTimer(this); 123 QObject::connect(slowMotionTimer, SIGNAL(timeout()), 124 this, SLOT(updateSlowMotion())); 125 126 movingCutpoint = false; 127 // Create blank pixmaps... 128 129 updateBackground(); 130 131 updateStats(); 132 133 setNoErase(); 134 gContext->addListener(this); 135 136 updateForeground(); 137 } 138 139 GridEditCutpoints::~GridEditCutpoints() 140 { 141 if (m_images) 142 { 143 delete m_images; 144 m_images = NULL; 145 } 146 gContext->removeListener(this); 147 } 148 149 void GridEditCutpoints::displayInitialFrame() 150 { 151 refreshImages(true); 152 refreshCutList(); 153 updateStats(); 154 SetUpdating(false); 155 } 156 157 void GridEditCutpoints::updateSlowMotion() 158 { 159 if (!slowMotionActive) 160 slowMotionTimer->stop(); 161 else if (readyForNextFrame && slowMotionDirection != 0) 162 { 163 readyForNextFrame=false; 164 165 if (slowMotionDirection > 0) 166 EditHandleRight(); 167 else if (slowMotionDirection < 0) 168 EditHandleLeft(); 169 } 170 } 171 172 173 void GridEditCutpoints::setSlowMotionSpeed() 174 { 175 // slowMotionDirection is max FPS 176 177 if (slowMotionDirection != 0) 178 { 179 int smd = slowMotionDirection; 180 if (smd < 0) smd = -smd; 181 int timeout = 1000 / smd; 182 183 slowMotionTimer->start(timeout); 184 } 185 SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection)); 186 } 187 188 189 void GridEditCutpoints::keyPressEvent(QKeyEvent *e) 190 { 191 // keyDown limits keyrepeats to prevent continued scrolling 192 // after key is released. Note: Qt's keycompress should handle 193 // this but will fail with fast key strokes and keyboard repeat 194 // enabled. Keys will not be marked as autorepeat and flood buffer. 195 // setFocusPolicy(QWidget::ClickFocus) in constructor is important 196 // or keyRelease events will not be received after a refocus. 197 198 bool handled = false; 199 200 QStringList actions; 201 gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions); 202 203 { 204 for (unsigned int i = 0; i < actions.size() && !handled; i++) 205 { 206 QString action = actions[i]; 207 handled = true; 208 209 if (action == "SELECT") 210 { 211 if (slowMotionActive) 212 { 213 slowMotionActive = false; 214 slowMotionTimer->stop(); 215 } 216 else if (movingCutpoint) 217 { 218 // Move cutpoint 219 m_player->DeleteMark(savedCutpoint); 220 m_player->AddMark(m_images->GetCurrentFrameNumber(), savedCutType); 221 movingCutpoint = false; 222 refreshCutList(); 223 refreshImages(); 224 } 225 else 226 handleSelect(); 227 } 228 else if (action == "PAUSE") 229 { 230 if (movingCutpoint) 231 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 232 "Moving Cutpoint", 233 "Slow Motion Unavailable when moving cutpoint"); 234 else if (slowMotionActive) 235 { 236 slowMotionActive = false; 237 slowMotionTimer->stop(); 238 } 239 } 240 else if (action == "SLOWMO") 241 { 242 if (movingCutpoint) 243 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 244 "Moving Cutpoint", 245 "Slow Motion Unavailable when moving cutpoint"); 246 else 247 { 248 if (slowMotionActive) 249 { 250 slowMotionActive = false; 251 slowMotionTimer->stop(); 252 } 253 else 254 { 255 slowMotionActive = true; 256 readyForNextFrame = true; 257 slowMotionDirection = 1; 258 259 // force to either 1 frame. 1/2 page or full page motion 260 int i; 261 // move to 1 frame if on cutpoint 262 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 263 m_player->UpdateSeekAmount(true); 264 265 // move to fullpage if higher 266 for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++) 267 m_player->UpdateSeekAmount(false); 268 269 setSlowMotionSpeed(); 270 } 271 } 272 } 273 else if (action == "LEFT") 274 { 275 if (slowMotionActive) 276 { 277 slowMotionDirection--; 278 setSlowMotionSpeed(); 279 } 280 else 281 { 282 SetUpdating(true); 283 284 EditHandleLeft(); 285 refreshImages(false); 286 } 287 } 288 else if (action == "RIGHT" ) 289 { 290 if (slowMotionActive) 291 { 292 slowMotionDirection++; 293 setSlowMotionSpeed(); 294 } 295 else 296 { 297 SetUpdating(true); 298 299 EditHandleRight(); 300 refreshImages(false); 301 } 302 } 303 else if (action == "UP") 304 m_player->UpdateSeekAmount(true); 305 else if (action == "DOWN") 306 { 307 if ((movingCutpoint || slowMotionActive) && m_player->GetSeekAmountPos() == 2) 308 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 309 "Moving Cutpoint", 310 "CutPoint skip Unavailable"); 311 else 312 m_player->UpdateSeekAmount(false); 313 } 314 else if (action == "CLEARMAP") 315 { 316 if (movingCutpoint || slowMotionActive) 317 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 318 "Moving Cutpoint", 319 "Clear Cut Map Unavailable"); 320 else 321 { 322 SetUpdating(true); 323 m_player->EditHandleClearMap(); 324 refreshCutList(); 325 } 326 } 327 else if (action == "INVERTMAP") 328 { 329 if (movingCutpoint || slowMotionActive) 330 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 331 "Moving Cutpoint", 332 "Invert Cut Map Unavailable"); 333 else 334 { 335 SetUpdating(true); 336 m_player->EditHandleInvertMap(); 337 refreshCutList(); 338 } 339 } 340 else if (action == "LOADCOMMSKIP") 341 { 342 if (movingCutpoint || slowMotionActive) 343 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 344 "Moving Cutpoint", 345 "Load Comm Skip Map Unavailable"); 346 else 347 { 348 SetUpdating(true); 349 m_player->EditHandleLoadCommSkip(); 350 refreshCutList(); 351 } 352 } 353 else if (action == "PREVCUT") 354 { 355 if (movingCutpoint || slowMotionActive) 356 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 357 "Moving Cutpoint", 358 "Prev Cut Unavailable"); 359 else 360 { 361 SetUpdating(true); 362 EditHandlePrevCut(); 363 refreshImages(false); 364 } 365 } 366 else if (action == "NEXTCUT") 367 { 368 if (movingCutpoint || slowMotionActive) 369 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 370 "Moving Cutpoint", 371 "Next Cut Unavailable"); 372 else 373 { 374 SetUpdating(true); 375 EditHandleNextCut(); 376 refreshImages(false); 377 } 378 } 379 else if (action == "BIGJUMPREW") 380 { 381 SetUpdating(true); 382 EditHandleBigJumpRew(); 383 refreshImages(false); 384 } 385 else if (action == "BIGJUMPFWD") 386 { 387 SetUpdating(true); 388 EditHandleBigJumpFwd(); 389 refreshImages(false); 390 } 391 else if (action == "ESCAPE" && movingCutpoint) 392 movingCutpoint = false; 393 else if (action == "ESCAPE" || action == "TOGGLEEDIT" || 394 action == "MENU") 395 escape(); 396 else 397 handled = false; 398 399 if (handled) 400 updateStats(); 401 if (movingCutpoint) 402 SetUpdating(true, "Moving Cutpoint"); 403 else if (!slowMotionActive) 404 SetUpdating(false); 405 } 406 } 407 408 if (!handled) 409 MythDialog::keyPressEvent(e); 410 } 411 412 void GridEditCutpoints::EditHandleLeft(int seektype) 413 { 414 long long seekamount = m_player->GetSeekAmount(); 415 bool cutpointseek = false; 416 417 if (seektype == -2 || seekamount == -2) 418 cutpointseek = true; 419 else 420 { 421 // seektype == 1 for normal, 10 for bigjump 422 seekamount *= seektype; 423 } 424 425 if (seekamount < 0) // Invalid -- keyframe 426 seekamount = 1; 427 428 m_images->SeekLeft(seekamount, cutpointseek); 429 430 refreshImages(true); 431 432 } 433 434 void GridEditCutpoints::EditHandleRight(int seektype) 435 { 436 long long seekamount = m_player->GetSeekAmount(); 437 bool cutpointseek=false; 438 439 if (seektype == -2 || seekamount == -2) 440 cutpointseek = true; 441 else 442 { 443 // seektype == 1 for normal, 10 for bigjump 444 seekamount *= seektype; 445 } 446 447 if (seekamount < 0) // Invalid -- keyframe 448 seekamount = 1; 449 450 m_images->SeekRight(seekamount, cutpointseek); 451 452 refreshImages(true); 453 454 } 455 456 void GridEditCutpoints::handleSelect(void) 457 { 458 bool needupdate = false; 459 // add / update cutpoint 460 // -or- 461 // delete / flip / move cutpoint 462 463 // if no cut points on screen 464 // "Delete Before" 465 // "Delete After" 466 467 // if on existing cutpoint 468 // "Delete cutpoint" 469 // "Flip directions" 470 471 // FIXME 472 // if a cutpoint exists on the screen but not on the current frame 473 // "Move to current frame" 474 // "Add new" 475 476 FrameStats fs = m_images->GetMainFrameStats(); 477 DeletePointInfo dpi = m_player->GetDeletePointInfo(fs.frameNumber, true); 478 479 if (fs.cutInd >= 2) 480 { 481 QString title = ""; 482 QString message = "Cutpoint exists:"; 483 QStringList buttons; 484 buttons.append("Delete cutpoint?"); 485 buttons.append("Move cutpoint?"); 486 if (fs.cutInd == 2) 487 buttons.append("Flip directions (Cut After)?"); 488 else 489 buttons.append("Flip directions (Cut Before)?"); 490 491 DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(), 492 title, message, buttons, kDialogCodeButton0); 493 494 495 if (dc != kDialogCodeRejected) 496 { 497 needupdate = true; 498 if (dc == kDialogCodeButton0) 499 // Delete cutpoint 500 m_player->DeleteMark(fs.frameNumber); 501 502 else if (dc == kDialogCodeButton1) 503 { 504 // Move cutpoint 505 savedCutpoint = fs.frameNumber; 506 savedCutType = m_player->deleteMap[fs.frameNumber]; 507 movingCutpoint = true; 508 // Ensure we're at least at 1 frame motion 509 int i; 510 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 511 m_player->UpdateSeekAmount(true); 512 513 } 514 else if (dc == kDialogCodeButton2) 515 // Flip 516 m_player->ReverseMark(fs.frameNumber); 517 } 518 } 519 else 520 { 521 QString title = ""; 522 QString message = "Insert New Cutpoint?"; 523 QStringList buttons; 524 buttons.append("Delete before this frame"); 525 buttons.append("Delete after this frame"); 526 DialogCode default_cut = (dpi.cut_after ? kDialogCodeButton1: kDialogCodeButton0); 527 DialogCode dc = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(), 528 title, message, buttons, default_cut); 529 530 if (dc != kDialogCodeRejected) 531 { 532 needupdate = true; 533 if (dc == kDialogCodeButton0) 534 // Delete left 535 m_player->AddMark(fs.frameNumber, MARK_CUT_END); 536 537 else if (dc == kDialogCodeButton1) 538 // Delete Right 539 m_player->AddMark(fs.frameNumber, MARK_CUT_START); 540 } 541 } 542 543 if (needupdate) 544 { 545 refreshCutList(); 546 refreshImages(); 547 } 548 } 549 550 void GridEditCutpoints::refreshImages(bool mainFrameOnly) 551 { 552 // VERBOSE(VB_GENERAL, "Refreshing"); 553 m_images->refreshImages(m_gridimages, mainFrameOnly); 554 if (mainFrameOnly) 555 { 556 repaint(m_gridimages[0]->getOuterBorder(), false); 557 updateStats(true); 558 } 559 } 560 561 void GridEditCutpoints::refreshCutList() 562 { 563 m_images->refreshCutList(m_gridimages); 564 refreshSlider(); 565 } 566 567 void GridEditCutpoints::refreshSlider() 568 { 569 if (!m_slider) 570 return; 571 572 m_slider->ClearAll(); 573 574 const int CUT_LEFT = 0; 575 const int CUT_RIGHT = 1; 576 577 long long startpos = 0; 578 long long endpos = 0; 579 580 int lastdirection = CUT_LEFT; 581 582 QMap<long long, int> & deleteMap = m_player->deleteMap; 583 QMap<long long, int>::Iterator i = deleteMap.begin(); 584 for (; i != deleteMap.end(); ++i) 585 { 586 long long frame = i.key(); 587 int direction = i.data(); 588 589 if (direction == CUT_LEFT) 590 { 591 endpos = frame; 592 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 593 594 startpos = frame; 595 lastdirection = CUT_LEFT; 596 } 597 else if (direction == CUT_RIGHT) 598 { 599 if (lastdirection == CUT_RIGHT) 600 { 601 // continuing within a cutpoint 602 endpos = frame; 603 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 604 } 605 606 startpos = frame; 607 lastdirection = CUT_RIGHT; 608 } 609 } 610 611 if (lastdirection == CUT_RIGHT) 612 { 613 // continuing within a cutpoint 614 endpos = m_images->GetMaxFrameNumber(); 615 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 616 } 617 } 618 619 void GridEditCutpoints::updateStats(bool forcerepaint) 620 { 621 int secs, frames, ss, mm, hh; 622 623 FrameStats fs = m_images->GetMainFrameStats(); 624 625 secs = (int)(fs.frameNumber / m_player->GetFrameRate()); 626 frames = fs.frameNumber - (int)(secs * m_player->GetFrameRate()); 627 628 ss = secs; 629 mm = ss / 60; 630 ss %= 60; 631 hh = mm / 60; 632 mm %= 60; 633 634 char timestr[128]; 635 sprintf(timestr, "%d:%02d:%02d.%02d", hh, mm, ss, frames); 636 637 char framestr[128]; 638 sprintf(framestr, "%lld", fs.frameNumber); 639 640 if (m_time) 641 { 642 m_time->SetText(timestr); 643 if (forcerepaint) 644 repaint(m_time->getScreenArea()); 645 } 646 if (m_framenum) 647 { 648 m_framenum->SetText(framestr); 649 if (forcerepaint) 650 repaint(m_framenum->getScreenArea()); 651 } 652 if (m_cutind) 653 { 654 switch (fs.cutInd) { 655 case 0: m_cutind->SetText(""); break; 656 case 1: m_cutind->SetText("Cut"); break; 657 case 2: m_cutind->SetText("Cut Before"); break; 658 case 3: m_cutind->SetText("Cut After"); break; 659 } 660 if (forcerepaint) 661 repaint(m_cutind->getScreenArea()); 662 } 663 664 // Don't need to force update this 665 if (m_jumpstyle) 666 m_jumpstyle->SetText(m_player->GetSeekAmountText()); 667 668 if (m_slider) 669 m_slider->SetPosition(fs.frameNumber, fs.maxFrameNumber); 670 671 } 672 673 void GridEditCutpoints::escape() 674 { 675 // Make sure we're on the right frame when we go back to 676 // Normal edit mode 677 unsetCursor(); 678 accept(); 679 } 680 681 void GridEditCutpoints::SetUpdating(bool active, QString text) 682 { 683 if (m_updatingind) 684 { 685 //VERBOSE(VB_GENERAL, QString("Updating to %1").arg(active)); 686 if (active) 687 { 688 m_updatingind->show(); 689 m_updatingind->SetText(text); 690 } 691 else 692 m_updatingind->hide(); 693 repaint(m_updatingind->getScreenArea()); 694 } 695 } 696 697 void GridEditCutpoints::displayedFramesAreReady() 698 { 699 if (slowMotionActive) 700 { 701 readyForNextFrame=true; 702 if (!slowMotionTimer->isActive()) 703 slowMotionTimer->start(0); 704 } 705 } 706 -
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(bool mainFrameOnly = false); 27 void displayedFramesAreReady(); 28 29 protected: 30 GridEditCutpoints(MythMainWindow *parent, 31 NuppelVideoPlayer *player, const char *name = "GridEditCutpoints"); 32 ~GridEditCutpoints(); 33 34 void displayInitialFrame(); 35 36 void handleSelect(); 37 38 void updateStats(bool forcerepaint = false); 39 40 protected slots: 41 void escape(); 42 void updateSlowMotion(); 43 44 private: 45 void keyPressEvent(QKeyEvent *e); 46 47 // seektype == -2 - cutpoint seek 48 // seektype == 1 - normal seek 49 // seektype == 10 - large seek 50 void EditHandleLeft(int seektype = 1); 51 void EditHandleRight(int seektype = 1); 52 void EditHandlePrevCut() { EditHandleLeft(-2); }; 53 void EditHandleNextCut() { EditHandleRight(-2); }; 54 void EditHandleBigJumpRew() { EditHandleLeft(10); }; 55 void EditHandleBigJumpFwd() { EditHandleRight(10); }; 56 void setSlowMotionSpeed(); 57 void refreshCutList(); 58 void refreshSlider(); 59 60 void SetUpdating(bool active, QString text = "Updating"); 61 62 // Private Data 63 64 NuppelVideoPlayer *m_player; 65 GridEditImages *m_images; 66 67 int usedSubVideoCount; 68 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> m_gridimages; 69 70 long long savedCutpoint; 71 int savedCutType; 72 bool movingCutpoint; 73 74 UITextType *m_framenum; 75 UITextType *m_time; 76 UITextType *m_cutind; 77 UITextType *m_jumpstyle; 78 UITextType *m_updatingind; 79 80 UIGridEditSliderType *m_slider; 81 QTimer *slowMotionTimer; 82 int slowMotionDirection; 83 bool slowMotionActive; 84 bool readyForNextFrame; 85 }; 86 87 #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 GridEditImages::GridEditImages(GridEditCutpoints *editor, NuppelVideoPlayer *player) 29 { 30 m_editor = editor; 31 m_player = player; 32 usedSubVideoCount = 0; 33 34 lastmovewasright= true; 35 36 int i; 37 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 38 { 39 stillFrames[i] = NULL; 40 stillFramesBig[i] = NULL; 41 cutFrames[i] = 0; 42 } 43 44 // Get first frames... 45 stillMainFrameNumber = m_player->GetFramesPlayed(); 46 if (stillMainFrameNumber <= 0) 47 stillMainFrameNumber = 1; 48 49 // maxFrameNumber may be overridden if neccessary 50 maxFrameNumber = m_player->GetTotalFrameCount(); 51 maxFrameNumberNVP = m_player->GetTotalFrameCount(); 52 53 if (stillMainFrameNumber <= 0) 54 stillMainFrameNumber = 1; 55 56 if (stillMainFrameNumber > maxFrameNumber) 57 stillMainFrameNumber = maxFrameNumber; 58 59 getImagesTimer = new QTimer(this); 60 QObject::connect(getImagesTimer, SIGNAL(timeout()), 61 this, SLOT(updateAllFrames())); 62 63 64 } 65 66 GridEditImages::~GridEditImages() 67 { 68 clearStillFrames(); 69 m_player->EditSeekToFrame(stillMainFrameNumber); 70 } 71 72 QPixmap *GridEditImages::makeScaledPixmap(const QImage& qim, QSize sz) 73 { 74 QPixmap *retval; 75 if (qim.size() == sz) 76 { 77 retval = new QPixmap(qim); 78 } 79 else 80 { 81 retval = new QPixmap(sz); 82 retval->fill(Qt::black); 83 QPainter p(retval); 84 85 int tl_left = 0; 86 int tl_top = 0; 87 if (sz.width() > qim.width()) 88 tl_left += (sz.width() - qim.width()) / 2; 89 90 if (sz.height() > qim.height()) 91 tl_top += (sz.height() - qim.height()) / 2; 92 93 // VERBOSE(VB_GENERAL, QString("Size mismatch qim(%1, %2) != sz(%3, %4) Shift to (%5, %6)") 94 // .arg(qim.width()).arg(qim.height()) 95 // .arg(sz.width()).arg(sz.height()) 96 // .arg(tl_left).arg(tl_top)); 97 98 p.drawImage(tl_left, tl_top, qim); 99 } 100 return retval; 101 } 102 103 #define FRAME_DEBUG 0 104 105 void GridEditImages::getMainStillFrame() 106 { 107 if (!stillFrames[0]) 108 getSpecificFrame(0); 109 } 110 111 bool GridEditImages::getStillFrames(int limits, int maxcount) 112 { 113 // 114 // returns true if no more frames to get 115 116 // This will fill in all the missing frames in the cache 117 118 int i; 119 bool getFutureFramesFirst = false; 120 121 // Get Boundaries for Minus and Plus arrays 122 // Don't go to absolute end - it'll slow down seeking 123 // when you go 1 frame left and right 124 125 // Note starti is negative 126 // Negative frames are before the main frame 127 // Frame #0 is the main frame 128 // Positive frames are after the main frame 129 int starti = stillFrames.minIndex() + 4; 130 int endi = stillFrames.maxIndex() - 4; 131 if (limits == 0) // Current Display only 132 { 133 starti = -(usedSubVideoCount+1); 134 endi = usedSubVideoCount+1; 135 136 } 137 else if (limits == 1) // PreCache only 138 { 139 starti = -preCacheCountLeft; 140 endi = preCacheCountRight; 141 getFutureFramesFirst = lastmovewasright; 142 } 143 144 // Make sure we don't fall of the front of the file 145 if (stillMainFrameNumber + starti <= 0) 146 starti = -(stillMainFrameNumber-1); 147 148 // ... or the back of the file 149 if (endi > (maxFrameNumber - stillMainFrameNumber)) 150 endi = (maxFrameNumber - stillMainFrameNumber); 151 152 if (getFutureFramesFirst) 153 { 154 // If we're filling out the cache and the last move was to the right 155 // grab future frames first before and past frames 156 for (i = 1; i <= endi; i++) 157 { 158 if (!stillFrames[i]) 159 { 160 getSpecificFrame(i); 161 if (--maxcount == 0) return false; 162 } 163 } 164 } 165 166 // grab all appropriate frames 167 168 for (i = starti; i <= endi; i++) 169 { 170 if (!stillFrames[i]) 171 { 172 getSpecificFrame(i); 173 if (--maxcount == 0) return false; 174 } 175 } 176 177 return true; 178 } 179 180 void GridEditImages::getSpecificFrame(int i) 181 { 182 // i is the index withou the cache of frames 183 if (!stillFrames[i]) 184 { 185 // get this frame 186 long long targetFrame = stillMainFrameNumber + i; 187 188 if (!m_player->EditSeekToFrame(targetFrame)) 189 { 190 VERBOSE(VB_GENERAL, QString("Error seeking to Frame[%1] (frame # %2)") 191 .arg(i).arg(targetFrame)); 192 checkMaxFrameCount(); 193 194 stillFramesBig[i] = new QPixmap(videoSizeMain); 195 stillFramesBig[i]->fill(Qt::gray); 196 197 stillFrames[i] = new QPixmap(videoSizeSmall); 198 stillFrames[i]->fill(Qt::gray); 199 } 200 else 201 { 202 cutFrames[i] = m_player->GetCutStatus(targetFrame); 203 QImage qim = m_player->GetScreenGrabOfCurrentFrame(videoSizeMain); 204 205 stillFramesBig[i] = makeScaledPixmap(qim, videoSizeMain); 206 stillFrames[i] = makeScaledPixmap(qim.scale(videoSizeSmall, QImage::ScaleMin), 207 videoSizeSmall); 208 209 #if FRAME_DEBUG 210 VERBOSE(VB_GENERAL, QString("stillFrames[%1] = %2 (%3)") 211 .arg(i) 212 .arg(targetFrame) 213 .arg(cutFrames[i])); 214 #endif 215 } 216 } 217 } 218 219 void GridEditImages::SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall) 220 { 221 usedSubVideoCount = vcount; 222 preCacheCountLeft = vcount+1; 223 preCacheCountRight = vcount+1; 224 videoSizeMain = sizeMain; 225 videoSizeSmall = sizeSmall; 226 227 // start to grab the current images 228 getMainStillFrame(); 229 getImagesTimer->start(0); 230 } 231 232 void GridEditImages::SetPreCacheLeft(int pccount) 233 { 234 preCacheCountLeft = usedSubVideoCount + pccount; 235 preCacheCountRight = usedSubVideoCount + 1; 236 // pccount is too big, then it's a waste of tim to precache 237 // i.e. 1 second jumps... 238 // We'll end up just throwing the extra frames away 239 if (preCacheCountLeft > stillFrames.maxIndex()) 240 preCacheCountLeft = usedSubVideoCount + 1; 241 } 242 243 void GridEditImages::SetPreCacheRight(int pccount) 244 { 245 preCacheCountLeft = usedSubVideoCount + 1; 246 preCacheCountRight = usedSubVideoCount + pccount; 247 // pccount is too big, then it's a waste of tim to precache 248 // i.e. 1 second jumps... 249 // We'll end up just throwing the extra frames away 250 if (preCacheCountRight > stillFrames.maxIndex()) 251 preCacheCountRight = usedSubVideoCount + 1; 252 } 253 254 void GridEditImages::updateAllFrames() 255 { 256 // getStillFrames() returns 'true' when it's gotten all requested frames 257 258 // First call is to grab frames to be actively displayed 259 if (getStillFrames(0, 1)) 260 { 261 // Tell the editor that all of the currently display frames are ready 262 m_editor->displayedFramesAreReady(); 263 264 if (getStillFrames(1, 1)) // Second, try for pre-cache frames 265 { 266 if (getStillFrames(2, 1)) // Third, get any other frames till we've filled our storage 267 { 268 getImagesTimer->stop(); 269 } 270 } 271 } 272 273 m_editor->refreshImages(); 274 275 } 276 277 void GridEditImages::clearStillFrames() 278 { 279 int i; 280 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 281 { 282 if (stillFrames[i]) 283 { 284 delete stillFrames[i]; 285 stillFrames[i] = NULL; 286 } 287 if (stillFramesBig[i]) 288 { 289 delete stillFramesBig[i]; 290 stillFramesBig[i] = NULL; 291 } 292 cutFrames[i] = 0; 293 } 294 } 295 296 bool GridEditImages::shiftStillFramesLeft(long long offset) 297 { 298 if (offset > 2 * stillFrames.maxIndex()) 299 { 300 // Dump all cached data and re-get it 301 clearStillFrames(); 302 } 303 else if (offset < 0) 304 { 305 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 306 // Dump all cached data and re-get it 307 clearStillFrames(); 308 offset = 0; 309 } 310 else if (offset != 0) 311 { 312 // Shift backwards in the stream by offset 313 314 // All frames will actually shift to the right. 315 // frame 'n' will become frame 'n+1' 316 // frame stillFrameMinus[1] will become mainframe 317 // frame stillFramePlus[max] will drop off 318 319 // shove extra frames into the excess space above usedSubVideos 320 321 if (offset >= stillMainFrameNumber) 322 offset = (stillMainFrameNumber-1); 323 324 // printStillFrameStats("Before SL"); 325 int i,j; 326 int minIndex = stillFrames.minIndex(); 327 int maxIndex = stillFrames.maxIndex(); 328 for (i = 0; i < offset; i++) 329 { 330 331 if (stillFrames[maxIndex]) 332 { 333 delete stillFrames[maxIndex]; 334 delete stillFramesBig[maxIndex]; 335 } 336 337 for (j = maxIndex; j > minIndex; j--) { 338 stillFrames[j] = stillFrames[j-1]; 339 stillFramesBig[j] = stillFramesBig[j-1]; 340 cutFrames[j] = cutFrames[j-1]; 341 } 342 343 stillFrames[minIndex] = NULL; 344 stillFramesBig[minIndex] = NULL; 345 cutFrames[minIndex] = 0; 346 } 347 348 // printStillFrameStats("After SL"); 349 350 } 351 352 stillMainFrameNumber -= offset; 353 if (stillMainFrameNumber < 1) 354 stillMainFrameNumber = 1; 355 356 return (stillFramesBig[0] != NULL); 357 } 358 359 bool GridEditImages::shiftStillFramesRight(long long offset) 360 { 361 //VERBOSE(VB_GENERAL, QString("Offset = %1").arg(offset)); 362 if (offset > 2 * stillFrames.maxIndex()) 363 { 364 // Dump all cached data and re-get it 365 clearStillFrames(); 366 } 367 else if (offset < 0) 368 { 369 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 370 // Dump all cached data and re-get it 371 clearStillFrames(); 372 offset = 0; 373 } 374 else if (offset != 0) 375 { 376 377 // Shift forwards in the stream by offset 378 379 // All frames will actually shift to the left. 380 // frame 'n' will become frame 'n-1' 381 // frame stillFramePlus[1] will become mainframe 382 // frame stillFrameMinus[max] will drop off 383 384 // shove extra frames into the excess space above usedSubVideos 385 386 if (stillMainFrameNumber + offset > maxFrameNumber) 387 { 388 offset = (maxFrameNumber - stillMainFrameNumber); 389 VERBOSE(VB_GENERAL, QString("new Offset = %1").arg(offset)); 390 } 391 //printStillFrameStats("Before SR"); 392 393 int i,j; 394 int minIndex = stillFrames.minIndex(); 395 int maxIndex = stillFrames.maxIndex(); 396 397 for (i = 0; i < offset; i++) 398 { 399 if (stillFrames[minIndex]) 400 { 401 delete stillFrames[minIndex]; 402 delete stillFramesBig[minIndex]; 403 } 404 405 for (j = minIndex; j < maxIndex; j++) { 406 stillFrames[j] = stillFrames[j+1]; 407 stillFramesBig[j] = stillFramesBig[j+1]; 408 cutFrames[j] = cutFrames[j+1]; 409 } 410 411 stillFrames[maxIndex] = NULL; 412 stillFramesBig[maxIndex] = NULL; 413 cutFrames[maxIndex] = 0; 414 } 415 416 //printStillFrameStats("After SR"); 417 418 } 419 stillMainFrameNumber += offset; 420 if (stillMainFrameNumber > maxFrameNumber ) 421 stillMainFrameNumber = maxFrameNumber; 422 423 return (stillFramesBig[0] != NULL); 424 } 425 426 void GridEditImages::printStillFrameStats(QString caption) 427 { 428 int i; 429 // Debug info for frame cache 430 QString foundframes= caption + " Found Frames: "; 431 432 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 433 if (stillFrames[i]) 434 foundframes += QString("%1 ").arg(i); 435 436 VERBOSE(VB_GENERAL, foundframes); 437 } 438 439 void GridEditImages::refreshCutList(myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages) 440 { 441 int i; 442 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 443 { 444 if (stillFrames[i]) 445 { 446 cutFrames[i] = m_player->GetCutStatus(stillMainFrameNumber+i); 447 if (gridimages[i]) 448 gridimages[i]->setCutStatus(cutFrames[i]); 449 } 450 } 451 } 452 453 bool GridEditImages::refreshImages(myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages, 454 bool mainFrameOnly) 455 { 456 // VERBOSE(VB_GENERAL, "Start"); 457 bool alldone = true; 458 if (!stillFramesBig[0]) 459 VERBOSE(VB_GENERAL, QString("Null Big Main frame %1").arg(stillMainFrameNumber)); 460 gridimages[0]->setPixmap(stillFramesBig[0], 461 stillMainFrameNumber, 462 cutFrames[0]); 463 464 if (!mainFrameOnly) 465 { 466 int i; 467 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 468 { 469 if (i != 0) // index 0 done above already 470 { 471 if (stillFrames[i] == NULL) 472 alldone = false; 473 gridimages[i]->setPixmap(stillFrames[i], 474 (stillMainFrameNumber + i), 475 cutFrames[i]); 476 } 477 } 478 } 479 480 // VERBOSE(VB_GENERAL, "Finish"); 481 return alldone; 482 } 483 484 485 // Back up x frames 486 void GridEditImages::SeekLeft(long long seekamount, bool cutpointseek) 487 { 488 lastmovewasright = false; 489 getImagesTimer->stop(); 490 491 if (cutpointseek) 492 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, false); 493 494 //VERBOSE(VB_GENERAL, QString("SeekLeft %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 495 SetPreCacheLeft(seekamount); 496 if (!shiftStillFramesLeft(seekamount)) 497 { 498 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 499 // .arg(seekamount)); 500 // Need to grab the main frame 501 502 getMainStillFrame(); 503 } 504 505 getImagesTimer->start(0); 506 } 507 508 void GridEditImages::SeekRight(long long seekamount, bool cutpointseek) 509 { 510 lastmovewasright = true; 511 getImagesTimer->stop(); 512 513 if (cutpointseek) 514 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, true); 515 516 //VERBOSE(VB_GENERAL, QString("SeekRight %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 517 SetPreCacheLeft(seekamount); 518 if (!shiftStillFramesRight(seekamount)) 519 { 520 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 521 // .arg(seekamount)); 522 // Need to grab the main frame 523 524 getMainStillFrame(); 525 } 526 527 getImagesTimer->start(0); 528 } 529 530 void GridEditImages::checkMaxFrameCount() 531 { 532 long long tfc = m_player->GetTotalFrameCount(); 533 if (tfc != maxFrameNumberNVP) 534 { 535 VERBOSE(VB_GENERAL, QString("Updating: tfc %1, mfn %2, mfnNVP %3") 536 .arg(tfc).arg(maxFrameNumber).arg(maxFrameNumberNVP)); 537 // Check to see if things changed 538 maxFrameNumber = tfc; 539 maxFrameNumberNVP = tfc; 540 } 541 } 542 543 FrameStats GridEditImages::GetMainFrameStats() 544 { 545 FrameStats result; 546 547 result.frameNumber = stillMainFrameNumber; 548 result.cutInd = cutFrames[0]; 549 result.maxFrameNumber = maxFrameNumber; 550 551 return result; 552 } 553 -
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(myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages); 48 49 // return true if anything changed 50 bool refreshImages(myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> &gridimages, 51 bool mainFrameOnly); 52 53 void SeekLeft(long long seekamount, bool cutpointseek = false); 54 void SeekRight(long long seekamount, bool cutpointseek = false); 55 56 FrameStats GetMainFrameStats(); 57 long long GetCurrentFrameNumber() const { return stillMainFrameNumber; } 58 long long GetMaxFrameNumber() const { return maxFrameNumber; } 59 60 void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall); 61 62 protected slots: 63 void updateAllFrames(); 64 65 private: 66 // Private functions 67 void clearStillFrames(); 68 void printStillFrameStats(QString caption); 69 void checkMaxFrameCount(); 70 71 // 'limits' paramter for getStillFrames(): 72 // 0 = get on screen Frames only 73 // 1 = get preCache Frames only 74 // 2 = get any necessary frames 75 bool getStillFrames(int limits, int maxcount = 1000); 76 void getMainStillFrame(); 77 void getSpecificFrame(int frameindex); 78 79 // return true if anything changed 80 bool shiftStillFramesLeft(long long offset); 81 bool shiftStillFramesRight(long long offset); 82 83 QPixmap *makeScaledPixmap(const QImage& qim, QSize sz); 84 85 void SetPreCacheLeft(int pccount); 86 void SetPreCacheRight(int pccount); 87 88 // Private data 89 // These frames are in the cutlist 90 // 0 == not cut 91 // 1 == cut 92 // 2 == cutpoint (cut left) 93 // 3 == cutpoint (cut right) 94 myArray<int, MAX_SUB_VIDEOS> cutFrames; 95 96 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames; 97 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig; 98 99 QSize videoSizeMain; 100 QSize videoSizeSmall; 101 int usedSubVideoCount; 102 int preCacheCountLeft; 103 int preCacheCountRight; 104 bool lastmovewasright; 105 106 long long stillMainFrameNumber; // frame number for big still picture 107 long long currentFrameNumberNVP; // frame number the NVP should be on 108 long long maxFrameNumber; // max frame number override for NVP 109 long long maxFrameNumberNVP; // Original NVP number 110 111 GridEditCutpoints *m_editor; 112 NuppelVideoPlayer *m_player; 113 114 QTimer *getImagesTimer; 115 116 }; 117 118 #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);