Ticket #6322: 137-editgrid.seekamount.code.16.patch
File 137-editgrid.seekamount.code.16.patch, 85.7 KB (added by , 15 years ago) |
---|
-
mythtv/libs/libmyth/mythdialogs.cpp
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/mythdialogs.cpp release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/mythdialogs.h release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/uitypes.cpp release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/uitypes.h release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/xmlparse.cpp release.20019.0219b/mythtv/libs/libmyth/xmlparse.cpp
1442 1442 { 1443 1443 parseBlackHole(container, info); 1444 1444 } 1445 else if (info.tagName() == "grideditimage") 1446 { 1447 parseGridEditImage(container, info); 1448 } 1449 else if (info.tagName() == "grideditslider") 1450 { 1451 parseGridEditSlider(container, info); 1452 } 1445 1453 else if (info.tagName() == "area") 1446 1454 { 1447 1455 area = parseRect(getFirstText(info)); … … 3445 3453 container->AddType(bh); 3446 3454 } 3447 3455 3456 void XMLParse::parseGridEditImage(LayerSet *container, QDomElement &element) 3457 { 3458 QRect area; 3459 QColor outlineColor; 3460 QColor cutColor; 3461 QColor cutPointColor; 3462 bool haveOutlineColor = false; 3463 bool haveCutColor = false; 3464 bool haveCutPointColor = false; 3465 3466 QString name = element.attribute("name", ""); 3467 if (name.isNull() || name.isEmpty()) 3468 { 3469 cerr << "GridEditImage needs a name\n"; 3470 return; 3471 } 3472 3473 for (QDomNode child = element.firstChild(); !child.isNull(); 3474 child = child.nextSibling()) 3475 { 3476 QDomElement info = child.toElement(); 3477 if (!info.isNull()) 3478 { 3479 if (info.tagName() == "area") 3480 { 3481 area = parseRect(getFirstText(info)); 3482 normalizeRect(area); 3483 } 3484 else if (info.tagName() == "outlinecolor") 3485 { 3486 haveOutlineColor = true; 3487 outlineColor = getFirstText(info); 3488 } 3489 else if (info.tagName() == "cutcolor") 3490 { 3491 haveCutColor = true; 3492 cutColor = getFirstText(info); 3493 } 3494 else if (info.tagName() == "cutpointcolor") 3495 { 3496 haveCutPointColor = true; 3497 cutPointColor = getFirstText(info); 3498 } 3499 else 3500 { 3501 cerr << "Unknown: " << info.tagName() << " in Grid Edit Image\n"; 3502 return; 3503 } 3504 } 3505 } 3506 3507 if (!haveOutlineColor) 3508 { 3509 cerr << "Missing outlinecolor in Grid Edit Image\n"; 3510 return; 3511 } 3512 3513 if (!haveCutColor) 3514 { 3515 cerr << "Missing cutcolor in Grid Edit Image\n"; 3516 return; 3517 } 3518 3519 if (!haveCutPointColor) 3520 { 3521 cerr << "Missing cutpointcolor in Grid Edit Image\n"; 3522 return; 3523 } 3524 3525 UIGridEditImageType *gei = new UIGridEditImageType(name); 3526 gei->SetScreen(wmult, hmult); 3527 gei->setArea(area); 3528 gei->setOutlineColor(outlineColor); 3529 gei->setCutColor(cutColor); 3530 gei->setCutPointColor(cutPointColor); 3531 gei->SetParent(container); 3532 gei->calculateScreenArea(); 3533 gei->clearPixmap(false); 3534 container->AddType(gei); 3535 } 3536 3537 void XMLParse::parseGridEditSlider(LayerSet *container, QDomElement &element) 3538 { 3539 QRect area; 3540 QColor fillColor; 3541 QColor cutColor; 3542 QColor inCutColor; 3543 QColor cutPointColor; 3544 QColor positionColor; 3545 bool haveFillColor = false; 3546 bool haveCutColor = false; 3547 bool haveInCutColor = false; 3548 bool haveCutPointColor = false; 3549 bool havePositionColor = false; 3550 3551 QString name = element.attribute("name", ""); 3552 if (name.isNull() || name.isEmpty()) 3553 { 3554 cerr << "GridEditSlider needs a name\n"; 3555 return; 3556 } 3557 3558 for (QDomNode child = element.firstChild(); !child.isNull(); 3559 child = child.nextSibling()) 3560 { 3561 QDomElement info = child.toElement(); 3562 if (!info.isNull()) 3563 { 3564 if (info.tagName() == "area") 3565 { 3566 area = parseRect(getFirstText(info)); 3567 normalizeRect(area); 3568 } 3569 else if (info.tagName() == "fillcolor") 3570 { 3571 haveFillColor = true; 3572 fillColor = getFirstText(info); 3573 } 3574 else if (info.tagName() == "cutcolor") 3575 { 3576 haveCutColor = true; 3577 cutColor = getFirstText(info); 3578 } 3579 else if (info.tagName() == "incutcolor") 3580 { 3581 haveInCutColor = true; 3582 inCutColor = getFirstText(info); 3583 } 3584 else if (info.tagName() == "cutpointcolor") 3585 { 3586 haveCutPointColor = true; 3587 cutPointColor = getFirstText(info); 3588 } 3589 else if (info.tagName() == "positioncolor") 3590 { 3591 havePositionColor = true; 3592 positionColor = getFirstText(info); 3593 } 3594 else 3595 { 3596 cerr << "Unknown: " << info.tagName() << " in Grid Edit Slider\n"; 3597 return; 3598 } 3599 } 3600 } 3601 3602 if (!haveFillColor) 3603 { 3604 cerr << "Missing fillcolor in Grid Edit Slider\n"; 3605 return; 3606 } 3607 3608 if (!haveCutColor) 3609 { 3610 cerr << "Missing cutcolor in Grid Edit Slider\n"; 3611 return; 3612 } 3613 3614 if (!haveInCutColor) 3615 { 3616 cerr << "Missing incutcolor in Grid Edit Slider\n"; 3617 return; 3618 } 3619 3620 if (!haveCutPointColor) 3621 { 3622 cerr << "Missing cutpointcolor in Grid Edit Slider\n"; 3623 return; 3624 } 3625 3626 if (!havePositionColor) 3627 { 3628 cerr << "Missing positioncolor in Grid Edit Slider\n"; 3629 return; 3630 } 3631 3632 UIGridEditSliderType *ges = new UIGridEditSliderType(name); 3633 ges->SetScreen(wmult, hmult); 3634 ges->setArea(area); 3635 ges->setFillColor(fillColor); 3636 ges->setCutColor(cutColor); 3637 ges->setInCutColor(inCutColor); 3638 ges->setCutPointColor(cutPointColor); 3639 ges->setPositionColor(positionColor); 3640 ges->SetParent(container); 3641 ges->calculateScreenArea(); 3642 container->AddType(ges); 3643 } 3644 3448 3645 void XMLParse::parseListBtnArea(LayerSet *container, QDomElement &element) 3449 3646 { 3450 3647 int context = -1; -
mythtv/libs/libmyth/xmlparse.h
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmyth/xmlparse.h release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp release.20019.0219b/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 edit_scaled_img = tmpimage.scale(size, QImage::ScaleMin).swapRGB(); 1600 1601 return edit_scaled_img; 1602 } 1603 1529 1604 void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame) 1530 1605 { 1531 1606 if (frame) … … 4989 5064 4990 5065 dialogname = ""; 4991 5066 5067 osd->HideAllExcept("editmode"); 5068 4992 5069 QMap<QString, QString> infoMap; 4993 5070 m_playbackinfo->ToMap(infoMap); 4994 5071 osd->SetText("editmode", infoMap, -1); … … 5044 5121 m_playbackinfo->SetEditing(false); 5045 5122 } 5046 5123 5124 bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame) 5125 { 5126 bool tmpexactseeks = exactseeks; 5127 GetDecoder()->setExactSeeks(true); 5128 5129 // VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2") 5130 // .arg(GetFramesPlayed()) 5131 // .arg(targetFrame)); 5132 5133 if (framesPlayed > targetFrame) 5134 { 5135 // seek back 5136 rewindtime = framesPlayed - targetFrame; 5137 while (rewindtime != 0) 5138 usleep(1000); 5139 } 5140 else 5141 { 5142 // seek forward 5143 fftime = targetFrame - framesPlayed; 5144 while (fftime != 0) 5145 usleep(1000); 5146 5147 } 5148 // VERBOSE(VB_GENERAL, QString("After current frame = %1") 5149 // .arg(GetFramesPlayed())); 5150 GetDecoder()->setExactSeeks(tmpexactseeks); 5151 return (targetFrame == framesPlayed); 5152 } 5153 5154 void NuppelVideoPlayer::EditHandleClearMap() 5155 { 5156 QMap<long long, int>::Iterator it; 5157 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5158 osd->HideEditArrow(it.key(), it.data()); 5159 5160 deleteMap.clear(); 5161 UpdateEditSlider(); 5162 } 5163 5164 void NuppelVideoPlayer::EditHandleInvertMap() 5165 { 5166 QMap<long long, int>::Iterator it; 5167 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5168 ReverseMark(it.key()); 5169 5170 UpdateEditSlider(); 5171 UpdateTimeDisplay(); 5172 } 5173 5174 void NuppelVideoPlayer::EditHandleLoadCommSkip() 5175 { 5176 if (hascommbreaktable) 5177 { 5178 commBreakMapLock.lock(); 5179 QMap<long long, int>::Iterator it; 5180 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5181 { 5182 if (!deleteMap.contains(it.key())) 5183 { 5184 if (it.data() == MARK_COMM_START) 5185 AddMark(it.key(), MARK_CUT_START); 5186 else 5187 AddMark(it.key(), MARK_CUT_END); 5188 } 5189 } 5190 commBreakMapLock.unlock(); 5191 UpdateEditSlider(); 5192 UpdateTimeDisplay(); 5193 } 5194 } 5195 5047 5196 bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e) 5048 5197 { 5049 5198 bool handled = false; … … 5123 5272 UpdateTimeDisplay(); 5124 5273 } 5125 5274 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 } 5275 EditHandleClearMap(); 5134 5276 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 } 5277 EditHandleInvertMap(); 5143 5278 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 } 5279 EditHandleLoadCommSkip(); 5164 5280 else if (action == "PREVCUT") 5165 5281 { 5166 5282 int old_seekamount = seekamount; … … 5206 5322 UpdateEditSlider(); 5207 5323 UpdateTimeDisplay(); 5208 5324 } 5209 else if (action == "ESCAPE" || action == "MENU" || 5210 action == "TOGGLEEDIT") 5325 else if (action == "TOGGLEEDIT" || action == "MENU") 5326 m_tv->ShowEditRecordingGrid(); 5327 else if (action == "ESCAPE") 5211 5328 { 5212 5329 DisableEdit(); 5213 5330 retval = false; … … 5220 5337 return retval; 5221 5338 } 5222 5339 5340 void NuppelVideoPlayer::ShowEditRecordingGrid(void) 5341 { 5342 // Completely hide the OSD 5343 osd->HideAll(); 5344 hideedits = true; 5345 5346 GridEditCutpoints::Run(this); 5347 5348 if (grid_edit_image_buffer) 5349 { 5350 delete [] grid_edit_image_buffer; 5351 grid_edit_image_buffer = NULL; 5352 grid_edit_image_buffer_length = 0; 5353 } 5354 5355 allow_pagesize = false; 5356 hideedits = false; 5357 5358 // Show OSD 5359 5360 QMap<QString, QString> infoMap; 5361 m_playbackinfo->ToMap(infoMap); 5362 osd->SetText("editmode", infoMap, -1); 5363 5364 UpdateEditSlider(); 5365 UpdateTimeDisplay(); 5366 if (seekamountpos == 3 || seekamountpos == 4) 5367 UpdateSeekAmount(true); 5368 else 5369 UpdateSeekAmountDisplay(); 5370 5371 QMap<long long, int>::Iterator it; 5372 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5373 AddMark(it.key(), it.data()); 5374 } 5375 5223 5376 AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const 5224 5377 { 5225 5378 if (videoOutput) … … 5311 5464 5312 5465 void NuppelVideoPlayer::UpdateSeekAmount(bool up) 5313 5466 { 5314 if (seekamountpos > 0 && !up) 5315 seekamountpos--; 5316 if (seekamountpos < 9 && up) 5317 seekamountpos++; 5467 if (up) 5468 { 5469 if (seekamountpos < 11) 5470 seekamountpos++; 5471 if (allow_pagesize) 5472 { 5473 if (seekamountpos == 1) 5474 seekamountpos = 2; 5475 } 5476 else 5477 { 5478 if (seekamountpos == 3 || seekamountpos == 4) 5479 seekamountpos = 5; 5480 } 5481 } 5482 else 5483 { 5484 if (seekamountpos > 0) 5485 seekamountpos--; 5486 if (allow_pagesize) 5487 { 5488 if (seekamountpos == 1) 5489 seekamountpos =0; 5490 } 5491 else 5492 { 5493 if (seekamountpos == 3 || seekamountpos == 4) 5494 seekamountpos = 2; 5495 } 5496 } 5318 5497 5319 QString text = "";5498 QString text; 5320 5499 5321 5500 switch (seekamountpos) 5322 5501 { 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; 5502 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5503 5504 // Only for non-edit grid 5505 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5506 // Only for non-edit grid 5507 5508 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5509 5510 // Case 3 & 4 are for the edit grid only 5511 case 3: text = QObject::tr("1/2 Page"); seekamount = half_page; break; 5512 case 4: text = QObject::tr("Full Page"); seekamount = 2*half_page; break; 5513 // Case 3 & 4 are for the edit grid only 5514 5515 case 5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5516 case 6: text = QObject::tr("1 second"); seekamount = (int)roundf(video_frame_rate); break; 5517 case 7: text = QObject::tr("5 seconds"); seekamount = (int)roundf(video_frame_rate * 5); break; 5518 case 8: text = QObject::tr("20 seconds"); seekamount = (int)roundf(video_frame_rate * 20); break; 5519 case 9: text = QObject::tr("1 minute"); seekamount = (int)roundf(video_frame_rate * 60); break; 5520 case 10: text = QObject::tr("5 minutes"); seekamount = (int)roundf(video_frame_rate * 300); break; 5521 case 11: text = QObject::tr("10 minutes"); seekamount = (int)roundf(video_frame_rate * 600); break; 5522 default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break; 5334 5523 } 5335 5524 5525 seekamounttext = text; 5526 UpdateSeekAmountDisplay(); 5527 } 5528 5529 void NuppelVideoPlayer::UpdateSeekAmountDisplay(void) 5530 { 5336 5531 QMap<QString, QString> infoMap; 5337 infoMap["seekamount"] = text; 5338 osd->SetText("editmode", infoMap, -1); 5532 infoMap["seekamount"] = seekamounttext; 5533 if (!hideedits) 5534 osd->SetText("editmode", infoMap, -1); 5339 5535 } 5340 5536 5341 5537 void NuppelVideoPlayer::UpdateTimeDisplay(void) … … 5365 5561 infoMap["timedisplay"] = timestr; 5366 5562 infoMap["framedisplay"] = framestr; 5367 5563 infoMap["cutindicator"] = cutmarker; 5368 osd->SetText("editmode", infoMap, -1); 5564 if (!hideedits) 5565 osd->SetText("editmode", infoMap, -1); 5369 5566 } 5370 5567 5371 5568 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear) … … 5497 5694 5498 5695 void NuppelVideoPlayer::UpdateEditSlider(void) 5499 5696 { 5500 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5697 if (!hideedits) 5698 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5501 5699 } 5502 5700 5503 5701 void NuppelVideoPlayer::AddMark(long long frames, int type) 5504 5702 { 5505 5703 deleteMap[frames] = type; 5506 osd->ShowEditArrow(frames, totalFrames, type); 5704 if (!hideedits) 5705 osd->ShowEditArrow(frames, totalFrames, type); 5507 5706 } 5508 5707 5509 5708 void NuppelVideoPlayer::DeleteMark(long long frames) 5510 5709 { 5511 osd->HideEditArrow(frames, deleteMap[frames]); 5710 if (!hideedits) 5711 osd->HideEditArrow(frames, deleteMap[frames]); 5512 5712 deleteMap.remove(frames); 5513 5713 } 5514 5714 5515 5715 void NuppelVideoPlayer::ReverseMark(long long frames) 5516 5716 { 5517 osd->HideEditArrow(frames, deleteMap[frames]); 5717 if (!hideedits) 5718 osd->HideEditArrow(frames, deleteMap[frames]); 5518 5719 5519 5720 if (deleteMap[frames] == MARK_CUT_END) 5520 5721 deleteMap[frames] = MARK_CUT_START; 5521 5722 else 5522 5723 deleteMap[frames] = MARK_CUT_END; 5523 5724 5524 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5725 if (!hideedits) 5726 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5727 } 5728 5729 long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right) 5730 { 5731 QMap<long long, int>::Iterator i = deleteMap.begin(); 5732 long long framenum = -1; 5733 long long seekcount = 0; 5734 if (right) 5735 { 5736 for (; i != deleteMap.end(); ++i) 5737 { 5738 if (i.key() > baseframe) 5739 { 5740 framenum = i.key(); 5741 break; 5742 } 5743 } 5744 if (framenum == -1) 5745 framenum = totalFrames; 5746 seekcount = framenum - baseframe; 5747 } 5748 else 5749 { 5750 for (; i != deleteMap.end(); ++i) 5751 { 5752 if (i.key() >= baseframe) 5753 break; 5754 framenum = i.key(); 5755 } 5756 if (framenum == -1) 5757 framenum = 0; 5758 seekcount = baseframe - framenum; 5759 } 5760 return seekcount; 5525 5761 } 5526 5762 5527 5763 void NuppelVideoPlayer::HandleArbSeek(bool right) 5528 5764 { 5529 5765 if (seekamount == -2) 5530 5766 { 5531 QMap<long long, int>::Iterator i = deleteMap.begin(); 5532 long long framenum = -1; 5767 long long seekcount = CalcCutPointSeek(framesPlayed, right); 5533 5768 if (right) 5534 5769 { 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; 5770 fftime = seekcount; 5547 5771 while (fftime > 0) 5548 5772 usleep(1000); 5549 5773 } 5550 5774 else 5551 5775 { 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; 5776 rewindtime = seekcount; 5562 5777 while (rewindtime > 0) 5563 5778 usleep(1000); 5564 5779 } … … 5589 5804 UpdateEditSlider(); 5590 5805 } 5591 5806 5807 int NuppelVideoPlayer::GetCutStatus(long long testframe) const 5808 { 5809 int retval = 0; 5810 QMap<long long, int>::const_iterator i; 5811 i = deleteMap.find(testframe); 5812 if (i == deleteMap.end()) { 5813 // testframe is not an explicit cutpoint 5814 // See if it is in a deleted area 5815 if (IsInDelete(testframe)) 5816 retval = 1; 5817 } else { 5818 int direction = i.data(); 5819 if (direction == 0) 5820 retval = 2; 5821 else 5822 retval = 3; 5823 } 5824 5825 return retval; 5826 } 5827 5592 5828 bool NuppelVideoPlayer::IsInDelete(long long testframe) const 5593 5829 { 5594 5830 long long startpos = 0; -
mythtv/libs/libmythtv/NuppelVideoPlayer.h
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/NuppelVideoPlayer.h release.20019.0219b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
102 102 103 103 class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 104 104 { 105 friend class GridEditCutpoints; 106 friend class TV; 105 107 public: 106 108 NuppelVideoPlayer(QString inUseID = "Unknown", 107 109 const ProgramInfo *info = NULL); … … 270 272 bool EnableEdit(void); 271 273 bool DoKeypress(QKeyEvent *e); 272 274 bool GetEditMode(void) const { return editmode; } 275 bool GetHideEdits(void) const { return hideedits; } 273 276 274 277 // Decoder stuff.. 275 278 VideoFrame *GetNextVideoFrame(bool allow_unsafe = true); … … 289 292 void ShutdownYUVResize(void); 290 293 void SaveScreenshot(void); 291 294 295 // Edit stuff 296 bool EditSeekToFrame(long long targetFrame); 297 QImage GetScreenGrabOfCurrentFrame(QSize size); // Get current frame 298 299 void EditHandleClearMap(); 300 void EditHandleInvertMap(); 301 void EditHandleLoadCommSkip(); 302 303 void ShowEditRecordingGrid(); 304 292 305 // Reinit 293 306 void ReinitOSD(void); 294 307 void ReinitVideo(void); … … 406 419 hidedvdbutton = hide; 407 420 } 408 421 422 // Stuf for GridEditCutpoints 423 long long CalcCutPointSeek(long long baseframe, bool right); 424 // returns 425 // 0 - no cut 426 // 1 - is deleted 427 // 2 - cut left 428 // 3 - cut right 429 int GetCutStatus(long long testframe) const; 430 long long GetSeekAmount() { return seekamount; } 431 QString GetSeekAmountText() { return seekamounttext; } 432 409 433 protected: 410 434 void DisplayPauseFrame(void); 411 435 void DisplayNormalFrame(void); … … 488 512 void HandleResponse(void); 489 513 490 514 void UpdateTimeDisplay(void); 515 int GetSeekAmountPos() { return seekamountpos; } 491 516 void UpdateSeekAmount(bool up); 517 void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; } 518 void UpdateSeekAmountDisplay(void); 492 519 void UpdateEditSlider(void); 493 520 494 521 // Private A/V Sync Stuff … … 560 587 bool livetv; 561 588 bool watchingrecording; 562 589 bool editmode; 590 bool hideedits; 563 591 bool resetvideo; 564 592 bool using_null_videoout; 565 593 bool no_audio_in; … … 579 607 long long fftime; 580 608 /// 1..9 == keyframe..10 minutes. 0 == cut point 581 609 int seekamountpos; 610 /// Used for Grid Edit logic 611 bool allow_pagesize; 612 int half_page; 582 613 /// Seekable frame increment when not using exact seeks. 583 614 /// Usually equal to keyframedist. 584 615 int seekamount; 616 QString seekamounttext; // OSD seek units 585 617 /// Iff true we ignore seek amount and try to seek to an 586 618 /// exact frame ignoring key frame restrictions. 587 619 bool exactseeks; … … 714 746 QMutex yuv_lock; 715 747 QWaitCondition yuv_wait; 716 748 749 // EditGrid still image capture 750 unsigned char *grid_edit_image_buffer; 751 int grid_edit_image_buffer_length; 752 717 753 // Filters 718 754 QMutex videofiltersLock; 719 755 QString videoFiltersForProgram; -
mythtv/libs/libmythtv/grideditcutpoints.cpp
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/grideditcutpoints.cpp release.20019.0219b/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, "edit", "", name) 49 { 50 m_player = player; 51 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 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 (images) 142 { 143 delete images; 144 images = NULL; 145 } 146 gContext->removeListener(this); 147 } 148 149 void GridEditCutpoints::displayInitialFrame() 150 { 151 images->getMainStillFrame(); 152 refreshImages(true); 153 refreshCutList(); 154 updateStats(); 155 SetUpdating(false); 156 images->getImagesTimer->start(0); 157 } 158 159 void GridEditCutpoints::updateSlowMotion() 160 { 161 if (!slowMotionActive) 162 slowMotionTimer->stop(); 163 else if (readyForNextFrame && slowMotionDirection != 0) 164 { 165 readyForNextFrame=false; 166 167 if (slowMotionDirection > 0) 168 images->EditHandleRight(); 169 else if (slowMotionDirection < 0) 170 images->EditHandleLeft(); 171 } 172 } 173 174 175 void GridEditCutpoints::setSlowMotionSpeed() 176 { 177 // slowMotionDirection is max FPS 178 179 if (slowMotionDirection != 0) 180 { 181 int smd = slowMotionDirection; 182 if (smd < 0) smd = -smd; 183 int timeout = 1000 / smd; 184 185 slowMotionTimer->start(timeout); 186 } 187 SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection)); 188 } 189 190 191 void GridEditCutpoints::keyPressEvent(QKeyEvent *e) 192 { 193 // keyDown limits keyrepeats to prevent continued scrolling 194 // after key is released. Note: Qt's keycompress should handle 195 // this but will fail with fast key strokes and keyboard repeat 196 // enabled. Keys will not be marked as autorepeat and flood buffer. 197 // setFocusPolicy(QWidget::ClickFocus) in constructor is important 198 // or keyRelease events will not be received after a refocus. 199 200 bool handled = false; 201 202 QStringList actions; 203 gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions); 204 205 { 206 for (unsigned int i = 0; i < actions.size() && !handled; i++) 207 { 208 QString action = actions[i]; 209 handled = true; 210 211 if (action == "SELECT") 212 { 213 if (slowMotionActive) 214 { 215 slowMotionActive = false; 216 slowMotionTimer->stop(); 217 } 218 else if (movingCutpoint) 219 { 220 // Move cutpoint 221 m_player->DeleteMark(savedCutpoint); 222 m_player->AddMark(images->stillMainFrameNumber, savedCutType); 223 movingCutpoint = false; 224 refreshCutList(); 225 refreshImages(); 226 } 227 else 228 handleSelect(); 229 } 230 else if (action == "PAUSE") 231 { 232 if (movingCutpoint) 233 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 234 "Moving Cutpoint", 235 "Slow Motion Unavailable when moving cutpoint"); 236 else if (slowMotionActive) 237 { 238 slowMotionActive = false; 239 slowMotionTimer->stop(); 240 } 241 } 242 else if (action == "SLOWMO") 243 { 244 if (movingCutpoint) 245 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 246 "Moving Cutpoint", 247 "Slow Motion Unavailable when moving cutpoint"); 248 else 249 { 250 if (slowMotionActive) 251 { 252 slowMotionActive = false; 253 slowMotionTimer->stop(); 254 } 255 else 256 { 257 slowMotionActive = true; 258 readyForNextFrame = true; 259 slowMotionDirection = 1; 260 261 // force to either 1 frame. 1/2 page or full page motion 262 int i; 263 // move to 1 frame if on cutpoint 264 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 265 m_player->UpdateSeekAmount(false); 266 267 // move to fullpage if higher 268 for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++) 269 m_player->UpdateSeekAmount(true); 270 271 setSlowMotionSpeed(); 272 } 273 } 274 } 275 else if (action == "LEFT") 276 { 277 if (slowMotionActive) 278 { 279 slowMotionDirection--; 280 setSlowMotionSpeed(); 281 } 282 else 283 { 284 SetUpdating(true); 285 286 images->EditHandleLeft(); 287 refreshImages(false); 288 } 289 } 290 else if (action == "RIGHT" ) 291 { 292 if (slowMotionActive) 293 { 294 slowMotionDirection++; 295 setSlowMotionSpeed(); 296 } 297 else 298 { 299 SetUpdating(true); 300 301 images->EditHandleRight(); 302 refreshImages(false); 303 } 304 } 305 else if (action == "UP") 306 m_player->UpdateSeekAmount(true); 307 else if (action == "DOWN") 308 { 309 if ((movingCutpoint || slowMotionActive) && m_player->GetSeekAmountPos() == 2) 310 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 311 "Moving Cutpoint", 312 "CutPoint skip Unavailable"); 313 else 314 m_player->UpdateSeekAmount(false); 315 } 316 else if (action == "CLEARMAP") 317 { 318 if (movingCutpoint || slowMotionActive) 319 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 320 "Moving Cutpoint", 321 "Clear Cut Map Unavailable"); 322 else 323 { 324 SetUpdating(true); 325 m_player->EditHandleClearMap(); 326 refreshCutList(); 327 } 328 } 329 else if (action == "INVERTMAP") 330 { 331 if (movingCutpoint || slowMotionActive) 332 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 333 "Moving Cutpoint", 334 "Invert Cut Map Unavailable"); 335 else 336 { 337 SetUpdating(true); 338 m_player->EditHandleInvertMap(); 339 refreshCutList(); 340 } 341 } 342 else if (action == "LOADCOMMSKIP") 343 { 344 if (movingCutpoint || slowMotionActive) 345 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 346 "Moving Cutpoint", 347 "Load Comm Skip Map Unavailable"); 348 else 349 { 350 SetUpdating(true); 351 m_player->EditHandleLoadCommSkip(); 352 refreshCutList(); 353 } 354 } 355 else if (action == "PREVCUT") 356 { 357 if (movingCutpoint || slowMotionActive) 358 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 359 "Moving Cutpoint", 360 "Prev Cut Unavailable"); 361 else 362 { 363 SetUpdating(true); 364 images->EditHandlePrevCut(); 365 refreshImages(false); 366 } 367 } 368 else if (action == "NEXTCUT") 369 { 370 if (movingCutpoint || slowMotionActive) 371 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 372 "Moving Cutpoint", 373 "Next Cut Unavailable"); 374 else 375 { 376 SetUpdating(true); 377 images->EditHandleNextCut(); 378 refreshImages(false); 379 } 380 } 381 else if (action == "BIGJUMPREW") 382 { 383 SetUpdating(true); 384 images->EditHandleBigJumpRew(); 385 refreshImages(false); 386 } 387 else if (action == "BIGJUMPFWD") 388 { 389 SetUpdating(true); 390 images->EditHandleBigJumpFwd(); 391 refreshImages(false); 392 } 393 else if (action == "ESCAPE" && movingCutpoint) 394 movingCutpoint = false; 395 else if (action == "ESCAPE" || action == "TOGGLEEDIT" || 396 action == "MENU") 397 escape(); 398 else 399 handled = false; 400 401 if (handled) 402 updateStats(); 403 if (movingCutpoint) 404 SetUpdating(true, "Moving Cutpoint"); 405 else if (!slowMotionActive) 406 SetUpdating(false); 407 } 408 } 409 410 if (!handled) 411 MythDialog::keyPressEvent(e); 412 } 413 414 void GridEditCutpoints::handleSelect(void) 415 { 416 bool needupdate = false; 417 // add / update cutpoint 418 // -or- 419 // delete / flip / move cutpoint 420 421 // if no cut points on screen 422 // "Delete Before" 423 // "Delete After" 424 425 // if on existing cutpoint 426 // "Delete cutpoint" 427 // "Flip directions" 428 429 // FIXME 430 // if a cutpoint exists on the screen but not on the current frame 431 // "Move to current frame" 432 // "Add new" 433 434 MythPopupBox *pub = new MythPopupBox(gContext->GetMainWindow(), "EDIT_SELECT"); 435 if (images->cutFrames[0] >= 2) 436 { 437 pub->addLabel("Cutpoint exists:"); 438 pub->addButton("Delete cutpoint?"); 439 pub->addButton("Move cutpoint?"); 440 if (images->cutFrames[0] == 2) 441 pub->addButton("Flip directions (Cut After)?"); 442 else 443 pub->addButton("Flip directions (Cut Before)?"); 444 DialogCode dc = pub->ExecPopup(); 445 446 if (dc != kDialogCodeRejected) 447 { 448 needupdate = true; 449 if (dc == kDialogCodeButton0) 450 // Delete cutpoint 451 m_player->DeleteMark(images->stillMainFrameNumber); 452 453 else if (dc == kDialogCodeButton1) 454 { 455 // Move cutpoint 456 savedCutpoint = images->stillMainFrameNumber; 457 savedCutType = m_player->deleteMap[images->stillMainFrameNumber]; 458 movingCutpoint = true; 459 // Ensure we're at least at 1 frame motion 460 int i; 461 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 462 m_player->UpdateSeekAmount(true); 463 464 } 465 else if (dc == kDialogCodeButton2) 466 // Flip 467 m_player->ReverseMark(images->stillMainFrameNumber); 468 } 469 } 470 else 471 { 472 pub->addLabel("Insert a new cut point?"); 473 pub->addButton("Delete before this frame"); 474 pub->addButton("Delete after this frame"); 475 DialogCode dc = pub->ExecPopup(); 476 477 if (dc != kDialogCodeRejected) 478 { 479 needupdate = true; 480 if (dc == kDialogCodeButton0) 481 // Delete left 482 m_player->AddMark(images->stillMainFrameNumber, MARK_CUT_END); 483 484 else if (dc == kDialogCodeButton1) 485 // Delete Right 486 m_player->AddMark(images->stillMainFrameNumber, MARK_CUT_START); 487 } 488 } 489 490 pub->deleteLater(); 491 if (needupdate) 492 { 493 refreshCutList(); 494 refreshImages(); 495 } 496 } 497 498 void GridEditCutpoints::customEvent(QCustomEvent *e) 499 { 500 if ((MythEvent::Type)(e->type()) == MythEvent::MythEventMessage) 501 { 502 MythEvent *me = (MythEvent *)e; 503 QString message = me->Message(); 504 } 505 } 506 507 void GridEditCutpoints::refreshImages(bool mainFrameOnly) 508 { 509 m_gridimages[0]->setPixmap(images->stillFramesBig[0], 510 images->stillMainFrameNumber, 511 images->cutFrames[0]); 512 513 if (mainFrameOnly) 514 { 515 repaint(m_gridimages[0]->getOuterBorder(), false); 516 updateStats(true); 517 return; 518 } 519 520 521 int i; 522 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 523 if (i != 0) // index 0 done above already 524 m_gridimages[i]->setPixmap(images->stillFrames[i], 525 (images->stillMainFrameNumber + i), 526 images->cutFrames[i]); 527 } 528 529 void GridEditCutpoints::printStillFrameStats(QString caption) 530 { 531 images->printStillFrameStats(caption); 532 } 533 534 void GridEditCutpoints::refreshCutList() 535 { 536 if (images->refreshCutList()) 537 { 538 int i; 539 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 540 m_gridimages[i]->setCutStatus(images->cutFrames[i]); 541 } 542 refreshSlider(); 543 } 544 545 void GridEditCutpoints::refreshSlider() 546 { 547 if (!m_slider) 548 return; 549 550 m_slider->ClearAll(); 551 552 const int CUT_LEFT = 0; 553 const int CUT_RIGHT = 1; 554 555 long long startpos = 0; 556 long long endpos = 0; 557 558 int lastdirection = CUT_LEFT; 559 560 QMap<long long, int> & deleteMap = m_player->deleteMap; 561 QMap<long long, int>::Iterator i = deleteMap.begin(); 562 for (; i != deleteMap.end(); ++i) 563 { 564 long long frame = i.key(); 565 int direction = i.data(); 566 567 if (direction == CUT_LEFT) 568 { 569 endpos = frame; 570 m_slider->SetRange(startpos, endpos, images->maxFrameNumber); 571 572 startpos = frame; 573 lastdirection = CUT_LEFT; 574 } 575 else if (direction == CUT_RIGHT) 576 { 577 if (lastdirection == CUT_RIGHT) 578 { 579 // continuing within a cutpoint 580 endpos = frame; 581 m_slider->SetRange(startpos, endpos, images->maxFrameNumber); 582 } 583 584 startpos = frame; 585 lastdirection = CUT_RIGHT; 586 } 587 } 588 589 if (lastdirection == CUT_RIGHT) 590 { 591 // continuing within a cutpoint 592 endpos = images->maxFrameNumber; 593 m_slider->SetRange(startpos, endpos, images->maxFrameNumber); 594 } 595 } 596 597 void GridEditCutpoints::updateStats(bool forcerepaint) 598 { 599 int secs, frames, ss, mm, hh; 600 601 secs = (int)(images->stillMainFrameNumber / m_player->GetFrameRate()); 602 frames = images->stillMainFrameNumber - (int)(secs * m_player->GetFrameRate()); 603 604 ss = secs; 605 mm = ss / 60; 606 ss %= 60; 607 hh = mm / 60; 608 mm %= 60; 609 610 char timestr[128]; 611 sprintf(timestr, "%d:%02d:%02d.%02d", hh, mm, ss, frames); 612 613 char framestr[128]; 614 sprintf(framestr, "%lld", images->stillMainFrameNumber); 615 616 if (m_time) 617 { 618 m_time->SetText(timestr); 619 if (forcerepaint) 620 repaint(m_time->getScreenArea()); 621 } 622 if (m_framenum) 623 { 624 m_framenum->SetText(framestr); 625 if (forcerepaint) 626 repaint(m_framenum->getScreenArea()); 627 } 628 if (m_cutind) 629 { 630 switch (images->cutFrames[0]) { 631 case 0: m_cutind->SetText(""); break; 632 case 1: m_cutind->SetText("Cut"); break; 633 case 2: m_cutind->SetText("Cut Before"); break; 634 case 3: m_cutind->SetText("Cut After"); break; 635 } 636 if (forcerepaint) 637 repaint(m_cutind->getScreenArea()); 638 } 639 640 // Don't need to force update this 641 if (m_jumpstyle) 642 m_jumpstyle->SetText(m_player->GetSeekAmountText()); 643 644 if (m_slider) 645 m_slider->SetPosition(images->stillMainFrameNumber, images->maxFrameNumber); 646 647 } 648 649 void GridEditCutpoints::escape() 650 { 651 // Make sure we're on the right frame when we go back to 652 // Normal edit mode 653 m_player->EditSeekToFrame(images->stillMainFrameNumber); 654 unsetCursor(); 655 accept(); 656 } 657 658 void GridEditCutpoints::SetUpdating(bool active, QString text) 659 { 660 if (m_updatingind) 661 { 662 //VERBOSE(VB_GENERAL, QString("Updating to %1").arg(active)); 663 if (active) 664 { 665 m_updatingind->show(); 666 m_updatingind->SetText(text); 667 } 668 else 669 m_updatingind->hide(); 670 repaint(m_updatingind->getScreenArea()); 671 } 672 } 673 674 void GridEditCutpoints::allFramesUpdated() 675 { 676 if (slowMotionActive) 677 { 678 readyForNextFrame=true; 679 if (!slowMotionTimer->isActive()) 680 slowMotionTimer->start(0); 681 } 682 } 683 -
mythtv/libs/libmythtv/grideditcutpoints.h
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/grideditcutpoints.h release.20019.0219b/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 protected slots: 27 void escape(); 28 void customEvent(QCustomEvent *e); 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 int getNearestCutpoint(); 39 40 void updateStats(bool forcerepaint = false); 41 42 private: 43 void keyPressEvent(QKeyEvent *e); 44 45 int usedSubVideoCount; 46 47 myArray<UIGridEditImageType*, MAX_SUB_VIDEOS> m_gridimages; 48 49 public: 50 void refreshImages(bool mainFrameOnly = false); 51 void allFramesUpdated(); 52 private: 53 void refreshCutList(); 54 void refreshSlider(); 55 56 57 GridEditImages *images; 58 59 void printStillFrameStats(QString ); 60 private: 61 void SetUpdating(bool active, QString text = "Updating"); 62 63 protected slots: 64 void updateSlowMotion(); 65 66 private: 67 void setSlowMotionSpeed(); 68 69 NuppelVideoPlayer *m_player; 70 71 long long savedCutpoint; 72 int savedCutType; 73 bool movingCutpoint; 74 75 UITextType *m_framenum; 76 UITextType *m_time; 77 UITextType *m_cutind; 78 UITextType *m_jumpstyle; 79 UITextType *m_updatingind; 80 81 UIGridEditSliderType *m_slider; 82 QTimer *slowMotionTimer; 83 int slowMotionDirection; 84 bool slowMotionActive; 85 bool readyForNextFrame; 86 }; 87 88 #endif -
mythtv/libs/libmythtv/grideditimages.cpp
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/grideditimages.cpp release.20019.0219b/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 } 70 71 QPixmap *GridEditImages::makeScaledPixmap(const QImage& qim, QSize sz) 72 { 73 QPixmap *retval; 74 if (qim.size() == sz) 75 { 76 retval = new QPixmap(qim); 77 } 78 else 79 { 80 retval = new QPixmap(sz); 81 retval->fill(Qt::black); 82 QPainter p(retval); 83 84 int tl_left = 0; 85 int tl_top = 0; 86 if (sz.width() > qim.width()) 87 tl_left += (sz.width() - qim.width()) / 2; 88 89 if (sz.height() > qim.height()) 90 tl_top += (sz.height() - qim.height()) / 2; 91 92 // VERBOSE(VB_GENERAL, QString("Size mismatch qim(%1, %2) != sz(%3, %4) Shift to (%5, %6)") 93 // .arg(qim.width()).arg(qim.height()) 94 // .arg(sz.width()).arg(sz.height()) 95 // .arg(tl_left).arg(tl_top)); 96 97 p.drawImage(tl_left, tl_top, qim); 98 } 99 return retval; 100 } 101 102 #define FRAME_DEBUG 0 103 104 void GridEditImages::getMainStillFrame() 105 { 106 if (!stillFrames[0]) 107 getSpecificFrame(0); 108 } 109 110 bool GridEditImages::getStillFrames(bool obeyPreCacheLimits, int maxcount) 111 { 112 // 113 // returns true if no more frames to get 114 115 // This will fill in all the missing frames in the cache 116 117 int i; 118 119 // Get Boundaries for Minus and Plus arrays 120 int starti = stillFrames.minIndex(); 121 int endi = stillFrames.maxIndex(); 122 if (obeyPreCacheLimits) 123 { 124 starti = -preCacheCountLeft; 125 endi = preCacheCountRight; 126 } 127 128 // Make sure we don't fall of the front of the file 129 if (stillMainFrameNumber + starti <= 0) 130 starti = -(stillMainFrameNumber-1); 131 132 // ... or the back of the file 133 if (endi > (maxFrameNumber - stillMainFrameNumber)) 134 endi = (maxFrameNumber - stillMainFrameNumber); 135 136 if (! obeyPreCacheLimits && lastmovewasright) 137 { 138 // If we're filling out the cache and the last move was to the right 139 // grab future frames first before and past frames 140 for (i = 1; i <= endi; i++) 141 { 142 if (!stillFrames[i]) 143 { 144 getSpecificFrame(i); 145 if (--maxcount == 0) return false; 146 } 147 } 148 } 149 150 // grab all appropriate frames 151 152 for (i = starti; i <= endi; i++) 153 { 154 if (!stillFrames[i]) 155 { 156 getSpecificFrame(i); 157 if (--maxcount == 0) return false; 158 } 159 } 160 161 return true; 162 } 163 164 void GridEditImages::getSpecificFrame(int i) 165 { 166 // i is the index withou the cache of frames 167 if (!stillFrames[i]) 168 { 169 // get this frame 170 long long targetFrame = stillMainFrameNumber + i; 171 172 if (!m_player->EditSeekToFrame(targetFrame)) 173 { 174 VERBOSE(VB_GENERAL, QString("Error seeking to Frame[%1] (frame # %2)") 175 .arg(i).arg(targetFrame)); 176 checkMaxFrameCount(); 177 178 stillFramesBig[i] = new QPixmap(videoSizeMain); 179 stillFramesBig[i]->fill(Qt::gray); 180 181 stillFrames[i] = new QPixmap(videoSizeSmall); 182 stillFrames[i]->fill(Qt::gray); 183 } 184 else 185 { 186 cutFrames[i] = m_player->GetCutStatus(targetFrame); 187 QImage qim = m_player->GetScreenGrabOfCurrentFrame(videoSizeMain); 188 189 stillFramesBig[i] = makeScaledPixmap(qim, videoSizeMain); 190 stillFrames[i] = makeScaledPixmap(qim.scale(videoSizeSmall, QImage::ScaleMin), 191 videoSizeSmall); 192 193 #if FRAME_DEBUG 194 VERBOSE(VB_GENERAL, QString("stillFrames[%1] = %2 (%3)") 195 .arg(i) 196 .arg(targetFrame) 197 .arg(cutFrames[i])); 198 #endif 199 } 200 } 201 } 202 203 void GridEditImages::SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall) 204 { 205 usedSubVideoCount = vcount; 206 preCacheCountLeft = vcount+1; 207 preCacheCountRight = vcount+1; 208 videoSizeMain = sizeMain; 209 videoSizeSmall = sizeSmall; 210 } 211 212 void GridEditImages::SetPreCacheLeft(int pccount) 213 { 214 preCacheCountLeft = usedSubVideoCount + pccount; 215 preCacheCountRight = usedSubVideoCount + 1; 216 // pccount is too big, then it's a waste of tim to precache 217 // i.e. 1 second jumps... 218 // We'll end up just throwing the extra frames away 219 if (preCacheCountLeft > stillFrames.maxIndex()) 220 preCacheCountLeft = usedSubVideoCount + 1; 221 } 222 223 void GridEditImages::SetPreCacheRight(int pccount) 224 { 225 preCacheCountLeft = usedSubVideoCount + 1; 226 preCacheCountRight = usedSubVideoCount + pccount; 227 // pccount is too big, then it's a waste of tim to precache 228 // i.e. 1 second jumps... 229 // We'll end up just throwing the extra frames away 230 if (preCacheCountRight > stillFrames.maxIndex()) 231 preCacheCountRight = usedSubVideoCount + 1; 232 } 233 234 void GridEditImages::updateAllFrames() 235 { 236 // First call is to grab frames to be actively displayed 237 bool done = getStillFrames(true, 1); 238 if (done) 239 { 240 m_editor->allFramesUpdated(); 241 242 // Second call willi be called to fill the image cache completely 243 done = getStillFrames(false, 1); 244 if (done) 245 getImagesTimer->stop(); 246 } 247 248 m_editor->refreshImages(); 249 250 } 251 252 void GridEditImages::clearStillFrames() 253 { 254 int i; 255 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 256 { 257 if (stillFrames[i]) 258 { 259 delete stillFrames[i]; 260 stillFrames[i] = NULL; 261 } 262 if (stillFramesBig[i]) 263 { 264 delete stillFramesBig[i]; 265 stillFramesBig[i] = NULL; 266 } 267 cutFrames[i] = 0; 268 } 269 } 270 271 bool GridEditImages::shiftStillFramesLeft(long long offset) 272 { 273 if (offset > 2 * stillFrames.maxIndex()) 274 { 275 // Dump all cached data and re-get it 276 clearStillFrames(); 277 } 278 else if (offset < 0) 279 { 280 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 281 // Dump all cached data and re-get it 282 clearStillFrames(); 283 offset = 0; 284 } 285 else if (offset != 0) 286 { 287 // Shift backwards in the stream by offset 288 289 // All frames will actually shift to the right. 290 // frame 'n' will become frame 'n+1' 291 // frame stillFrameMinus[1] will become mainframe 292 // frame stillFramePlus[max] will drop off 293 294 // shove extra frames into the excess space above usedSubVideos 295 296 if (offset >= stillMainFrameNumber) 297 offset = (stillMainFrameNumber-1); 298 299 // printStillFrameStats("Before SL"); 300 int i,j; 301 int minIndex = stillFrames.minIndex(); 302 int maxIndex = stillFrames.maxIndex(); 303 for (i = 0; i < offset; i++) 304 { 305 306 if (stillFrames[maxIndex]) 307 { 308 delete stillFrames[maxIndex]; 309 delete stillFramesBig[maxIndex]; 310 } 311 312 for (j = maxIndex; j > minIndex; j--) { 313 stillFrames[j] = stillFrames[j-1]; 314 stillFramesBig[j] = stillFramesBig[j-1]; 315 cutFrames[j] = cutFrames[j-1]; 316 } 317 318 stillFrames[minIndex] = NULL; 319 stillFramesBig[minIndex] = NULL; 320 cutFrames[minIndex] = 0; 321 } 322 323 // printStillFrameStats("After SL"); 324 325 } 326 327 stillMainFrameNumber -= offset; 328 if (stillMainFrameNumber < 1) 329 stillMainFrameNumber = 1; 330 331 return (stillFramesBig[0] != NULL); 332 } 333 334 bool GridEditImages::shiftStillFramesRight(long long offset) 335 { 336 //VERBOSE(VB_GENERAL, QString("Offset = %1").arg(offset)); 337 if (offset > 2 * stillFrames.maxIndex()) 338 { 339 // Dump all cached data and re-get it 340 clearStillFrames(); 341 } 342 else if (offset < 0) 343 { 344 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 345 // Dump all cached data and re-get it 346 clearStillFrames(); 347 offset = 0; 348 } 349 else if (offset != 0) 350 { 351 352 // Shift forwards in the stream by offset 353 354 // All frames will actually shift to the left. 355 // frame 'n' will become frame 'n-1' 356 // frame stillFramePlus[1] will become mainframe 357 // frame stillFrameMinus[max] will drop off 358 359 // shove extra frames into the excess space above usedSubVideos 360 361 if (stillMainFrameNumber + offset > maxFrameNumber) 362 { 363 offset = (maxFrameNumber - stillMainFrameNumber); 364 VERBOSE(VB_GENERAL, QString("new Offset = %1").arg(offset)); 365 } 366 //printStillFrameStats("Before SR"); 367 368 int i,j; 369 int minIndex = stillFrames.minIndex(); 370 int maxIndex = stillFrames.maxIndex(); 371 372 for (i = 0; i < offset; i++) 373 { 374 if (stillFrames[minIndex]) 375 { 376 delete stillFrames[minIndex]; 377 delete stillFramesBig[minIndex]; 378 } 379 380 for (j = minIndex; j < maxIndex; j++) { 381 stillFrames[j] = stillFrames[j+1]; 382 stillFramesBig[j] = stillFramesBig[j+1]; 383 cutFrames[j] = cutFrames[j+1]; 384 } 385 386 stillFrames[maxIndex] = NULL; 387 stillFramesBig[maxIndex] = NULL; 388 cutFrames[maxIndex] = 0; 389 } 390 391 //printStillFrameStats("After SR"); 392 393 } 394 stillMainFrameNumber += offset; 395 if (stillMainFrameNumber > maxFrameNumber ) 396 stillMainFrameNumber = maxFrameNumber; 397 398 return (stillFramesBig[0] != NULL); 399 } 400 401 void GridEditImages::printStillFrameStats(QString caption) 402 { 403 int i; 404 // Debug info for frame cache 405 QString foundframes= caption + " Found Frames: "; 406 407 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 408 if (stillFrames[i]) 409 foundframes += QString("%1 ").arg(i); 410 411 VERBOSE(VB_GENERAL, foundframes); 412 } 413 414 bool GridEditImages::refreshCutList() 415 { 416 // return true if the on-screen cutlist has changed 417 bool needupdate = false; 418 419 int i; 420 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 421 { 422 if (stillFrames[i]) 423 { 424 int oldcutvalue = cutFrames[i]; 425 cutFrames[i] = m_player->GetCutStatus(stillMainFrameNumber+i); 426 if (oldcutvalue != cutFrames[i] && frameIsDisplayed(i)) 427 needupdate = true; 428 } 429 } 430 431 return needupdate; 432 } 433 434 // Back up x frames 435 void GridEditImages::EditHandleLeft(int seektype) 436 { 437 lastmovewasright = false; 438 getImagesTimer->stop(); 439 long long seekamount = m_player->GetSeekAmount(); 440 441 if (seektype == -2 || seekamount == -2) 442 { 443 // CutPoint seek 444 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, false); 445 } 446 else 447 { 448 // seektype == 1 for normal, 10 for bigjump 449 seekamount *= seektype; 450 } 451 452 if (seekamount < 0) // Invalid -- keyframe 453 seekamount = 1; 454 455 SetPreCacheLeft(seekamount); 456 if (!shiftStillFramesLeft(seekamount)) 457 { 458 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 459 // .arg(seekamount)); 460 // Need to grab the main frame 461 462 getMainStillFrame(); 463 } 464 465 m_editor->refreshImages(true); 466 467 getImagesTimer->start(0); 468 469 } 470 471 void GridEditImages::EditHandleRight(int seektype) 472 { 473 lastmovewasright = true; 474 getImagesTimer->stop(); 475 long long seekamount = m_player->GetSeekAmount(); 476 477 if (seektype == -2 || seekamount == -2) 478 { 479 // CutPoint seek 480 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, true); 481 } 482 else 483 { 484 // seektype == 1 for normal, 10 for bigjump 485 seekamount *= seektype; 486 } 487 488 if (seekamount < 0) // Invalid -- keyframe 489 seekamount = 1; 490 491 SetPreCacheRight(seekamount); 492 if (!shiftStillFramesRight(seekamount)) 493 { 494 // Need to grab the main frame 495 //VERBOSE(VB_GENERAL, QString("shiftStillFramesRight(%1) == false") 496 // .arg(seekamount)); 497 498 getMainStillFrame(); 499 } 500 m_editor->refreshImages(true); 501 502 getImagesTimer->start(0); 503 } 504 505 void GridEditImages::checkMaxFrameCount() 506 { 507 long long tfc = m_player->GetTotalFrameCount(); 508 if (tfc != maxFrameNumberNVP) 509 { 510 VERBOSE(VB_GENERAL, QString("Updating: tfc %1, mfn %2, mfnNVP %3") 511 .arg(tfc).arg(maxFrameNumber).arg(maxFrameNumberNVP)); 512 // Check to see if things changed 513 maxFrameNumber = tfc; 514 maxFrameNumberNVP = tfc; 515 } 516 } 517 -
mythtv/libs/libmythtv/grideditimages.h
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/grideditimages.h release.20019.0219b/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 32 class MPUBLIC GridEditImages : public QObject 33 { 34 Q_OBJECT 35 36 public: 37 GridEditImages(GridEditCutpoints *er, NuppelVideoPlayer *player); 38 ~GridEditImages(); 39 40 void clearStillFrames(); 41 // return true if anything changed 42 bool shiftStillFramesLeft(long long offset); 43 bool shiftStillFramesRight(long long offset); 44 45 void printStillFrameStats(QString caption); 46 // return true if anything chagned 47 bool refreshCutList(); 48 49 // seektype == -2 - cutpoint seek 50 // seektype == 1 - normal seek 51 // seektype == 10 - large seek 52 void EditHandleLeft(int seektype = 1); 53 void EditHandleRight(int seektype = 1); 54 void EditHandlePrevCut() { EditHandleLeft(-2); }; 55 void EditHandleNextCut() { EditHandleRight(-2); }; 56 void EditHandleBigJumpRew() { EditHandleLeft(10); }; 57 void EditHandleBigJumpFwd() { EditHandleRight(10); }; 58 59 void checkMaxFrameCount(); 60 61 QPixmap *makeScaledPixmap(const QImage& qim, QSize sz); 62 63 bool getStillFrames(bool overPreCacheLimits, int maxcount = 1000); 64 void getMainStillFrame(); 65 void getSpecificFrame(int frameindex); 66 67 void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall); 68 void SetPreCacheLeft(int pccount); 69 void SetPreCacheRight(int pccount); 70 71 // These frames are in the cutlist 72 // 0 == not cut 73 // 1 == cut 74 // 2 == cutpoint (cut left) 75 // 3 == cutpoint (cut right) 76 myArray<int, MAX_SUB_VIDEOS> cutFrames; 77 78 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames; 79 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig; 80 81 // return true if the specified index is displayed on screen 82 bool frameIsDisplayed(int i) { return (-usedSubVideoCount <= i && i <= usedSubVideoCount);}; 83 84 QSize videoSizeMain; 85 QSize videoSizeSmall; 86 int usedSubVideoCount; 87 int preCacheCountLeft; 88 int preCacheCountRight; 89 90 long long stillMainFrameNumber; // frame number for big still picture 91 long long currentFrameNumberNVP; // frame number the NVP should be on 92 long long maxFrameNumber; // max frame number override for NVP 93 long long maxFrameNumberNVP; // Original NVP number 94 95 QTimer *getImagesTimer; 96 bool lastmovewasright; 97 protected slots: 98 void updateAllFrames(); 99 100 private: 101 GridEditCutpoints *m_editor; 102 NuppelVideoPlayer *m_player; 103 104 105 }; 106 107 #endif -
mythtv/libs/libmythtv/libmythtv.pro
diff -r -u -N -X diff.exclude -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/libmythtv.pro release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/tv_play.cpp release.20019.0219b/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 -x release.20019.0219a -x release.20019.0219b release.20019.0219a/mythtv/libs/libmythtv/tv_play.h release.20019.0219b/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);