Ticket #6322: 192-137-editgrid.patch
| File 192-137-editgrid.patch, 130.1 KB (added by , 16 years ago) |
|---|
-
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
old new using namespace std; 60 60 #include "mythverbose.h" 61 61 #include "myth_imgconvert.h" 62 62 63 #include "grideditcutpoints.h" 64 63 65 extern "C" { 64 66 #include "vbitext/vbi.h" 65 67 #include "vsync.h" … … static unsigned dbg_ident(const NuppelVi 89 91 #define LOC_WARN QString("NVP(%1), Warning: ").arg(dbg_ident(this),0,36) 90 92 #define LOC_ERR QString("NVP(%1), Error: ").arg(dbg_ident(this),0,36) 91 93 94 #ifndef FUNCTIONLOGGER 95 #define FUNCTIONLOGGER 96 #endif 97 92 98 uint track_type_to_display_mode[kTrackTypeCount+2] = 93 99 { 94 100 kDisplayNone, … … NuppelVideoPlayer::NuppelVideoPlayer(boo 117 123 decoder_thread_alive(true), killplayer(false), 118 124 killvideo(false), livetv(false), 119 125 watchingrecording(false), editmode(false), 126 hideedits(false), 120 127 resetvideo(false), using_null_videoout(false), 121 128 no_audio_in(false), no_audio_out(false), 122 129 transcoding(false), … … NuppelVideoPlayer::NuppelVideoPlayer(boo 128 135 bookmarkseek(0), 129 136 // Seek 130 137 fftime(0), seekamountpos(4), 131 seekamount(30), exactseeks(false), 138 allow_pagesize(false), half_page(0), 139 seekamount(30), seekamounttext("30 Frames"), 140 exactseeks(false), 132 141 // Playback misc. 133 142 videobuf_retries(0), framesPlayed(0), 134 143 totalFrames(0), totalLength(0), … … NuppelVideoPlayer::NuppelVideoPlayer(boo 179 188 yuv_need_copy(false), yuv_desired_size(0,0), 180 189 yuv_scaler(NULL), yuv_frame_scaled(NULL), 181 190 yuv_scaler_in_size(0,0), yuv_scaler_out_size(0,0), 191 // Grid Editing 192 grid_edit_image_scaler(NULL), grid_edit_image_small_scaler(NULL), 193 grid_edit_image_buffer_yuv(NULL), grid_edit_image_small_buffer_yuv(NULL), 194 grid_edit_image_buffer_rgb(NULL), grid_edit_image_small_buffer_rgb(NULL), 195 grid_edit_image_buffer_length(0), grid_edit_image_small_buffer_length(0), 196 grid_edit_image_in_size(-1, -1), 197 182 198 // Filters 183 199 videoFiltersForProgram(""), videoFiltersOverride(""), 184 200 postfilt_width(0), postfilt_height(0), … … NuppelVideoPlayer::~NuppelVideoPlayer(vo 338 354 output_jmeter = NULL; 339 355 } 340 356 357 ClearScreenGrab(); 358 341 359 ShutdownYUVResize(); 342 360 } 343 361 … … VideoFrame *NuppelVideoPlayer::GetCurren 1594 1612 return retval; 1595 1613 } 1596 1614 1615 bool NuppelVideoPlayer::GetScreenGrabsOfCurrentFrame(QImage &normal, QImage &small) 1616 { 1617 FUNCTIONLOGGER; 1618 unsigned char *data = NULL; 1619 VideoFrame *frame = NULL; 1620 AVPicture orig; 1621 AVPicture scaled_yuv; 1622 AVPicture scaled_rgb; 1623 AVPicture scaled_yuv_small; 1624 AVPicture scaled_rgb_small; 1625 bzero(&orig, sizeof(AVPicture)); 1626 bzero(&scaled_yuv, sizeof(AVPicture)); 1627 bzero(&scaled_rgb, sizeof(AVPicture)); 1628 bzero(&scaled_yuv_small, sizeof(AVPicture)); 1629 bzero(&scaled_rgb_small, sizeof(AVPicture)); 1630 1631 int vw, vh; 1632 if (!(frame = GetCurrentFrame(vw, vh))) 1633 { 1634 return false; 1635 } 1636 1637 if (!(data = frame->buf)) 1638 { 1639 ReleaseCurrentFrame(frame); 1640 return false; 1641 } 1642 1643 { 1644 QMutexLocker l(&videofiltersLock); 1645 1646 // Check to see if the screen dimensions have changed 1647 // Probably shouldn't happen in normal use. 1648 if (grid_edit_image_in_size != video_dim) 1649 SetupScreenGrab(); 1650 1651 avpicture_fill(&orig, data, PIX_FMT_YUV420P, 1652 video_dim.width(), video_dim.height()); 1653 1654 avpicture_deinterlace(&orig, &orig, PIX_FMT_YUV420P, 1655 video_dim.width(), video_dim.height()); 1656 1657 // Rescale to the normal size 1658 avpicture_fill(&scaled_yuv, grid_edit_image_buffer_yuv, PIX_FMT_YUV420P, 1659 grid_edit_image_size.width(), 1660 grid_edit_image_size.height()); 1661 1662 avpicture_fill(&scaled_rgb, grid_edit_image_buffer_rgb, PIX_FMT_RGB32, 1663 grid_edit_image_size.width(), 1664 grid_edit_image_size.height()); 1665 1666 sws_scale(grid_edit_image_scaler, orig.data, orig.linesize, 0, 1667 video_dim.height(), 1668 scaled_yuv.data, scaled_yuv.linesize); 1669 1670 myth_sws_img_convert( 1671 &scaled_rgb, PIX_FMT_RGB32, &scaled_yuv, PIX_FMT_YUV420P, 1672 grid_edit_image_size.width(), grid_edit_image_size.height()); 1673 1674 1675 // Rescale to the small size 1676 avpicture_fill(&scaled_yuv_small, grid_edit_image_small_buffer_yuv, PIX_FMT_YUV420P, 1677 grid_edit_image_small_size.width(), 1678 grid_edit_image_small_size.height()); 1679 1680 avpicture_fill(&scaled_rgb_small, grid_edit_image_small_buffer_rgb, PIX_FMT_RGB32, 1681 grid_edit_image_small_size.width(), 1682 grid_edit_image_small_size.height()); 1683 1684 sws_scale(grid_edit_image_small_scaler, orig.data, orig.linesize, 0, 1685 video_dim.height(), 1686 scaled_yuv_small.data, scaled_yuv_small.linesize); 1687 1688 myth_sws_img_convert( 1689 &scaled_rgb_small, PIX_FMT_RGB32, &scaled_yuv_small, PIX_FMT_YUV420P, 1690 grid_edit_image_small_size.width(), grid_edit_image_small_size.height()); 1691 1692 } 1693 1694 // Don't need the current frame anymore so release it 1695 ReleaseCurrentFrame(frame); 1696 1697 1698 #ifdef MMX 1699 #define _RGBSWAP .rgbSwapped() 1700 #endif 1701 1702 normal = QImage(grid_edit_image_buffer_rgb, 1703 grid_edit_image_size.width(), grid_edit_image_size.height(), 1704 QImage::Format_RGB32)_RGBSWAP; 1705 1706 small = QImage(grid_edit_image_small_buffer_rgb, 1707 grid_edit_image_small_size.width(), grid_edit_image_small_size.height(), 1708 QImage::Format_RGB32)_RGBSWAP; 1709 1710 return true; 1711 } 1712 1713 void NuppelVideoPlayer::SetScreenGrabSizes(QSize normal, QSize small) 1714 { 1715 grid_edit_image_size = normal; 1716 grid_edit_image_small_size = small; 1717 1718 SetupScreenGrab(); 1719 VERBOSE(VB_GENERAL, QString("Main Image = (%1, %2) from (%3, %4)") 1720 .arg(grid_edit_image_size.width()) 1721 .arg(grid_edit_image_size.height()) 1722 .arg(normal.width()).arg(normal.height())); 1723 VERBOSE(VB_GENERAL, QString("Small Image = (%1, %2) from (%3, %4)") 1724 .arg(grid_edit_image_small_size.width()) 1725 .arg(grid_edit_image_small_size.height()) 1726 .arg(small.width()).arg(small.height())); 1727 1728 } 1729 1730 void NuppelVideoPlayer::ClearScreenGrab() 1731 { 1732 if (grid_edit_image_scaler) 1733 { 1734 sws_freeContext(grid_edit_image_scaler); 1735 grid_edit_image_scaler = NULL; 1736 } 1737 1738 if (grid_edit_image_small_scaler) 1739 { 1740 sws_freeContext(grid_edit_image_small_scaler); 1741 grid_edit_image_small_scaler=NULL; 1742 } 1743 1744 if (grid_edit_image_buffer_yuv) 1745 { 1746 delete grid_edit_image_buffer_yuv; 1747 grid_edit_image_buffer_yuv=NULL; 1748 } 1749 1750 if (grid_edit_image_small_buffer_yuv) 1751 { 1752 delete grid_edit_image_small_buffer_yuv; 1753 grid_edit_image_small_buffer_yuv=NULL; 1754 } 1755 1756 if (grid_edit_image_buffer_rgb) 1757 { 1758 delete grid_edit_image_buffer_rgb; 1759 grid_edit_image_buffer_rgb=NULL; 1760 } 1761 1762 if (grid_edit_image_small_buffer_rgb) 1763 { 1764 delete grid_edit_image_small_buffer_rgb; 1765 grid_edit_image_small_buffer_rgb=NULL; 1766 } 1767 } 1768 1769 void NuppelVideoPlayer::SetupScreenGrab() 1770 { 1771 ClearScreenGrab(); 1772 grid_edit_image_in_size = video_dim; 1773 1774 // Normalize the output sizes. 1775 // This is necessary to preserve the aspect ratio 1776 1777 QSize tmpsize = grid_edit_image_size; 1778 grid_edit_image_size = video_dim; 1779 grid_edit_image_size.scale(tmpsize, Qt::KeepAspectRatio); 1780 1781 tmpsize = grid_edit_image_small_size; 1782 grid_edit_image_small_size = video_dim; 1783 grid_edit_image_small_size.scale(tmpsize, Qt::KeepAspectRatio); 1784 1785 grid_edit_image_size = QSize(grid_edit_image_size.width() & ~0x7, 1786 grid_edit_image_size.height() & ~0x7); 1787 grid_edit_image_small_size = QSize(grid_edit_image_small_size.width() & ~0x7, 1788 grid_edit_image_small_size.height() & ~0x7); 1789 1790 // Do normal first 1791 uint sz = grid_edit_image_size.width() * grid_edit_image_size.height(); 1792 grid_edit_image_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128]; 1793 grid_edit_image_buffer_rgb = new unsigned char[sz * 4 + 128]; 1794 1795 //grid_edit_image_scaler = img_resample_init( 1796 // grid_edit_image_size.width(), grid_edit_image_size.height(), 1797 // grid_edit_image_in_size.width(), grid_edit_image_in_size.height()); 1798 1799 grid_edit_image_scaler = sws_getCachedContext(grid_edit_image_scaler, 1800 grid_edit_image_in_size.width(), grid_edit_image_in_size.height(), 1801 PIX_FMT_YUV420P, 1802 grid_edit_image_size.width(), grid_edit_image_size.height(), 1803 PIX_FMT_YUV420P, 1804 SWS_FAST_BILINEAR, NULL, NULL, NULL); 1805 1806 // Then small 1807 sz = grid_edit_image_small_size.width() * grid_edit_image_small_size.height(); 1808 grid_edit_image_small_buffer_yuv = new unsigned char[(sz * 3 / 2) + 128]; 1809 grid_edit_image_small_buffer_rgb = new unsigned char[sz * 4 + 128]; 1810 1811 // Resize from normal to small 1812 //grid_edit_image_small_scaler = img_resample_init( 1813 // grid_edit_image_small_size.width(), grid_edit_image_small_size.height(), 1814 // grid_edit_image_size.width(), grid_edit_image_size.height()); 1815 1816 grid_edit_image_small_scaler = sws_getCachedContext(grid_edit_image_small_scaler, 1817 grid_edit_image_in_size.width(), grid_edit_image_in_size.height(), 1818 PIX_FMT_YUV420P, 1819 grid_edit_image_small_size.width(), grid_edit_image_small_size.height(), 1820 PIX_FMT_YUV420P, 1821 SWS_FAST_BILINEAR, NULL, NULL, NULL); 1822 } 1823 1597 1824 void NuppelVideoPlayer::ReleaseCurrentFrame(VideoFrame *frame) 1598 1825 { 1599 1826 if (frame) … … bool NuppelVideoPlayer::EnableEdit(void) 4855 5082 4856 5083 dialogname = ""; 4857 5084 5085 osd->HideAllExcept("editmode"); 5086 4858 5087 InfoMap infoMap; 4859 5088 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 4860 5089 player_ctx->playingInfo->ToMap(infoMap); … … void NuppelVideoPlayer::DisableEdit(void 4919 5148 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 4920 5149 } 4921 5150 5151 bool NuppelVideoPlayer::EditSeekToFrame(long long targetFrame) 5152 { 5153 bool tmpexactseeks = exactseeks; 5154 GetDecoder()->setExactSeeks(true); 5155 5156 // VERBOSE(VB_GENERAL, QString("Before current frame = %1, going to frame %2") 5157 // .arg(GetFramesPlayed()) 5158 // .arg(targetFrame)); 5159 5160 if (framesPlayed > targetFrame) 5161 { 5162 // seek back 5163 rewindtime = framesPlayed - targetFrame; 5164 while (rewindtime != 0) 5165 usleep(1000); 5166 } 5167 else 5168 { 5169 // seek forward 5170 fftime = targetFrame - framesPlayed; 5171 while (fftime != 0) 5172 usleep(1000); 5173 5174 } 5175 // VERBOSE(VB_GENERAL, QString("After current frame = %1") 5176 // .arg(GetFramesPlayed())); 5177 GetDecoder()->setExactSeeks(tmpexactseeks); 5178 return (targetFrame == framesPlayed); 5179 } 5180 5181 void NuppelVideoPlayer::EditHandleClearMap() 5182 { 5183 QMap<long long, int>::Iterator it; 5184 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5185 osd->HideEditArrow(it.key(), *it); 5186 5187 deleteMap.clear(); 5188 UpdateEditSlider(); 5189 } 5190 5191 void NuppelVideoPlayer::EditHandleInvertMap() 5192 { 5193 QMap<long long, int>::Iterator it; 5194 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5195 ReverseMark(it.key()); 5196 5197 UpdateEditSlider(); 5198 UpdateTimeDisplay(); 5199 } 5200 5201 void NuppelVideoPlayer::EditHandleLoadCommSkip() 5202 { 5203 if (hascommbreaktable) 5204 { 5205 commBreakMapLock.lock(); 5206 QMap<long long, int>::Iterator it; 5207 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5208 { 5209 if (!deleteMap.contains(it.key())) 5210 { 5211 if (*it == MARK_COMM_START) 5212 AddMark(it.key(), MARK_CUT_START); 5213 else 5214 AddMark(it.key(), MARK_CUT_END); 5215 } 5216 } 5217 commBreakMapLock.unlock(); 5218 UpdateEditSlider(); 5219 UpdateTimeDisplay(); 5220 } 5221 } 5222 4922 5223 bool NuppelVideoPlayer::DoKeypress(QKeyEvent *e) 4923 5224 { 5225 4924 5226 bool handled = false; 4925 5227 QStringList actions; 4926 5228 handled = gContext->GetMainWindow()->TranslateKeyPress("TV Editing", e, actions); … … bool NuppelVideoPlayer::DoKeypress(QKeyE 5001 5303 UpdateTimeDisplay(); 5002 5304 } 5003 5305 else if (action == "CLEARMAP") 5004 { 5005 QMap<long long, int>::Iterator it; 5006 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5007 osd->HideEditArrow(it.key(), *it); 5008 5009 deleteMap.clear(); 5010 UpdateEditSlider(); 5011 } 5306 EditHandleClearMap(); 5012 5307 else if (action == "INVERTMAP") 5013 { 5014 QMap<long long, int>::Iterator it; 5015 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5016 ReverseMark(it.key()); 5017 5018 UpdateEditSlider(); 5019 UpdateTimeDisplay(); 5020 } 5308 EditHandleInvertMap(); 5021 5309 else if (action == "LOADCOMMSKIP") 5022 { 5023 if (hascommbreaktable) 5024 { 5025 commBreakMapLock.lock(); 5026 QMap<long long, int>::Iterator it; 5027 for (it = commBreakMap.begin(); it != commBreakMap.end(); ++it) 5028 { 5029 if (!deleteMap.contains(it.key())) 5030 { 5031 if (*it == MARK_COMM_START) 5032 AddMark(it.key(), MARK_CUT_START); 5033 else 5034 AddMark(it.key(), MARK_CUT_END); 5035 } 5036 } 5037 commBreakMapLock.unlock(); 5038 UpdateEditSlider(); 5039 UpdateTimeDisplay(); 5040 } 5041 } 5310 EditHandleLoadCommSkip(); 5042 5311 else if (action == "PREVCUT") 5043 5312 { 5044 5313 int old_seekamount = seekamount; … … bool NuppelVideoPlayer::DoKeypress(QKeyE 5084 5353 UpdateEditSlider(); 5085 5354 UpdateTimeDisplay(); 5086 5355 } 5087 else if (action == "ESCAPE" || action == "MENU" || 5088 action == "EDIT") 5356 else if (action == "EDIT" || action == "MENU") 5357 { 5358 m_tv->ShowEditRecordingGrid(); 5359 } 5360 else if (action == "ESCAPE") 5089 5361 { 5090 5362 DisableEdit(); 5091 5363 retval = false; … … bool NuppelVideoPlayer::DoKeypress(QKeyE 5098 5370 return retval; 5099 5371 } 5100 5372 5373 void NuppelVideoPlayer::StartEditRecordingGrid(void) 5374 { 5375 { 5376 QMutexLocker l(&grid_edit_lock); 5377 if (hideedits) 5378 return; 5379 5380 hideedits = true; 5381 } 5382 5383 // Completely hide the OSD 5384 osd->HideAll(); 5385 } 5386 5387 void NuppelVideoPlayer::EndEditRecordingGrid(void) 5388 { 5389 5390 ClearScreenGrab(); 5391 5392 allow_pagesize = false; 5393 { 5394 QMutexLocker l(&grid_edit_lock); 5395 5396 hideedits = false; 5397 5398 // Show OSD 5399 5400 InfoMap infoMap; 5401 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 5402 player_ctx->playingInfo->ToMap(infoMap); 5403 infoMap.detach(); 5404 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 5405 5406 osd->SetText("editmode", infoMap, -1); 5407 5408 UpdateEditSlider(); 5409 UpdateTimeDisplay(); 5410 if (seekamountpos == 3 || seekamountpos == 4) 5411 UpdateSeekAmount(true); 5412 else 5413 UpdateSeekAmountDisplay(); 5414 5415 QMap<long long, int>::Iterator it; 5416 for (it = deleteMap.begin(); it != deleteMap.end(); ++it) 5417 AddMark(it.key(), *it); 5418 } 5419 } 5420 5101 5421 AspectOverrideMode NuppelVideoPlayer::GetAspectOverride(void) const 5102 5422 { 5103 5423 if (videoOutput) … … bool NuppelVideoPlayer::IsEmbedding(void 5184 5504 5185 5505 void NuppelVideoPlayer::UpdateSeekAmount(bool up) 5186 5506 { 5187 if (seekamountpos > 0 && !up) 5188 seekamountpos--; 5189 if (seekamountpos < 9 && up) 5190 seekamountpos++; 5507 if (up) 5508 { 5509 if (seekamountpos < 11) 5510 seekamountpos++; 5511 if (allow_pagesize) 5512 { 5513 if (seekamountpos == 1) 5514 seekamountpos = 2; 5515 } 5516 else 5517 { 5518 if (seekamountpos == 3 || seekamountpos == 4) 5519 seekamountpos = 5; 5520 } 5521 } 5522 else 5523 { 5524 if (seekamountpos > 0) 5525 seekamountpos--; 5526 if (allow_pagesize) 5527 { 5528 if (seekamountpos == 1) 5529 seekamountpos =0; 5530 } 5531 else 5532 { 5533 if (seekamountpos == 3 || seekamountpos == 4) 5534 seekamountpos = 2; 5535 } 5536 } 5191 5537 5192 5538 QString text = ""; 5193 5539 5194 5540 switch (seekamountpos) 5195 5541 { 5196 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5197 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5198 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5199 case 3: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5200 case 4: text = QObject::tr("%n second(s)", "", 1); seekamount = (int)roundf(video_frame_rate); break; 5201 case 5: text = QObject::tr("%n second(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 5); break; 5202 case 6: text = QObject::tr("%n second(s)", "", 20); seekamount = (int)roundf(video_frame_rate * 20); break; 5203 case 7: text = QObject::tr("%n minute(s)", "", 1); seekamount = (int)roundf(video_frame_rate * 60); break; 5204 case 8: text = QObject::tr("%n minute(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 300); break; 5205 case 9: text = QObject::tr("%n minute(s)", "", 10); seekamount = (int)roundf(video_frame_rate * 600); break; 5542 case 0: text = QObject::tr("cut point"); seekamount = -2; break; 5543 5544 // Only for non-edit grid 5545 case 1: text = QObject::tr("keyframe"); seekamount = -1; break; 5546 // Only for non-edit grid 5547 5548 case 2: text = QObject::tr("1 frame"); seekamount = 1; break; 5549 5550 // Case 3 & 4 are for the edit grid only 5551 case 3: text = QObject::tr("1/2 Page"); seekamount = half_page; break; 5552 case 4: text = QObject::tr("Full Page"); seekamount = 2*half_page; break; 5553 // Case 3 & 4 are for the edit grid only 5554 5555 case 5: text = QObject::tr("0.5 seconds"); seekamount = (int)roundf(video_frame_rate / 2); break; 5556 case 6: text = QObject::tr("%n second(s)", "", 1); seekamount = (int)roundf(video_frame_rate); break; 5557 case 7: text = QObject::tr("%n second(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 5); break; 5558 case 8: text = QObject::tr("%n second(s)", "", 20); seekamount = (int)roundf(video_frame_rate * 20); break; 5559 case 9: text = QObject::tr("%n minute(s)", "", 1); seekamount = (int)roundf(video_frame_rate * 60); break; 5560 case 10: text = QObject::tr("%n minute(s)", "", 5); seekamount = (int)roundf(video_frame_rate * 300); break; 5561 case 11: text = QObject::tr("%n minute(s)", "", 10); seekamount = (int)roundf(video_frame_rate * 600); break; 5206 5562 default: text = QObject::tr("error"); seekamount = (int)roundf(video_frame_rate); break; 5207 5563 } 5208 5564 5565 seekamounttext = text; 5566 UpdateSeekAmountDisplay(); 5567 } 5568 5569 void NuppelVideoPlayer::UpdateSeekAmountDisplay(void) 5570 { 5209 5571 InfoMap infoMap; 5210 infoMap["seekamount"] = text; 5211 osd->SetText("editmode", infoMap, -1); 5572 infoMap["seekamount"] = seekamounttext; 5573 if (!hideedits) 5574 osd->SetText("editmode", infoMap, -1); 5212 5575 } 5213 5576 5214 5577 void NuppelVideoPlayer::UpdateTimeDisplay(void) … … void NuppelVideoPlayer::UpdateTimeDispla 5238 5601 infoMap["timedisplay"] = timestr; 5239 5602 infoMap["framedisplay"] = framestr; 5240 5603 infoMap["cutindicator"] = cutmarker; 5241 osd->SetText("editmode", infoMap, -1); 5604 if (!hideedits) 5605 osd->SetText("editmode", infoMap, -1); 5242 5606 } 5243 5607 5244 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear)5608 DeletePointInfo NuppelVideoPlayer::GetDeletePointInfo(long long frame, bool allowSelectNear) 5245 5609 { 5246 bool deletepoint = false; 5247 bool cut_after = false; 5248 int direction = 0; 5610 DeletePointInfo retval; 5249 5611 5250 5612 if(!deleteMap.isEmpty()) 5251 5613 { 5252 5614 QMap<long long, int>::ConstIterator iter = deleteMap.begin(); 5253 5615 5254 while((iter != deleteMap.end()) && (iter.key() < frame sPlayed))5616 while((iter != deleteMap.end()) && (iter.key() < frame)) 5255 5617 ++iter; 5256 5618 5257 5619 if (iter == deleteMap.end()) 5258 5620 { 5259 5621 --iter; 5260 cut_after = !(*iter);5622 retval.cut_after = !(*iter); 5261 5623 } 5262 else if((iter != deleteMap.begin()) && (iter.key() != frame sPlayed))5624 else if((iter != deleteMap.begin()) && (iter.key() != frame)) 5263 5625 { 5264 5626 long long value = iter.key(); 5265 if((framesPlayed - (--iter).key()) > (value - frame sPlayed))5627 if((framesPlayed - (--iter).key()) > (value - frame)) 5266 5628 { 5267 cut_after = !(*iter);5629 retval.cut_after = !(*iter); 5268 5630 ++iter; 5269 5631 } 5270 5632 else 5271 cut_after = !(*iter);5633 retval.cut_after = !(*iter); 5272 5634 } 5273 5635 5274 direction = (*iter);5275 deleteframe = iter.key();5636 retval.direction = (*iter); 5637 retval.deleteframe = iter.key(); 5276 5638 5277 if ((absLongLong( deleteframe - framesPlayed) <5639 if ((absLongLong(retval.deleteframe - frame) < 5278 5640 (int)ceil(20 * video_frame_rate)) && !allowSelectNear) 5279 5641 { 5280 deletepoint = true;5642 retval.deletepoint = true; 5281 5643 } 5282 5644 } 5645 return retval; 5646 } 5647 5648 void NuppelVideoPlayer::HandleSelect(bool allowSelectNear) 5649 { 5650 DeletePointInfo dpi = GetDeletePointInfo(framesPlayed, allowSelectNear); 5651 deleteframe = dpi.deleteframe; 5283 5652 5284 if (d eletepoint)5653 if (dpi.deletepoint) 5285 5654 { 5286 5655 QString message = QObject::tr("You are close to an existing cut point. " 5287 5656 "Would you like to:"); … … void NuppelVideoPlayer::HandleSelect(boo 5289 5658 QString option2 = QObject::tr("Move this cut point to the current " 5290 5659 "position"); 5291 5660 QString option3 = QObject::tr("Flip directions - delete to the "); 5292 if (d irection == 0)5661 if (dpi.direction == 0) 5293 5662 option3 += QObject::tr("right"); 5294 5663 else 5295 5664 option3 += QObject::tr("left"); … … void NuppelVideoPlayer::HandleSelect(boo 5319 5688 options += option1; 5320 5689 options += option2; 5321 5690 5322 osd->NewDialogBox(dialogname, message, options, -1, cut_after);5691 osd->NewDialogBox(dialogname, message, options, -1, dpi.cut_after); 5323 5692 } 5324 5693 } 5325 5694 … … void NuppelVideoPlayer::HandleResponse(v 5370 5739 5371 5740 void NuppelVideoPlayer::UpdateEditSlider(void) 5372 5741 { 5373 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5742 if (!hideedits) 5743 osd->DoEditSlider(deleteMap, framesPlayed, totalFrames); 5374 5744 } 5375 5745 5376 5746 void NuppelVideoPlayer::AddMark(long long frames, int type) 5377 5747 { 5378 5748 deleteMap[frames] = type; 5379 osd->ShowEditArrow(frames, totalFrames, type); 5749 if (!hideedits) 5750 osd->ShowEditArrow(frames, totalFrames, type); 5380 5751 } 5381 5752 5382 5753 void NuppelVideoPlayer::DeleteMark(long long frames) 5383 5754 { 5384 osd->HideEditArrow(frames, deleteMap[frames]); 5755 if (!hideedits) 5756 osd->HideEditArrow(frames, deleteMap[frames]); 5385 5757 deleteMap.remove(frames); 5386 5758 } 5387 5759 5388 5760 void NuppelVideoPlayer::ReverseMark(long long frames) 5389 5761 { 5390 osd->HideEditArrow(frames, deleteMap[frames]); 5762 if (!hideedits) 5763 osd->HideEditArrow(frames, deleteMap[frames]); 5391 5764 5392 5765 if (deleteMap[frames] == MARK_CUT_END) 5393 5766 deleteMap[frames] = MARK_CUT_START; 5394 5767 else 5395 5768 deleteMap[frames] = MARK_CUT_END; 5396 5769 5397 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5770 if (!hideedits) 5771 osd->ShowEditArrow(frames, totalFrames, deleteMap[frames]); 5398 5772 } 5399 5773 5400 void NuppelVideoPlayer::HandleArbSeek(bool right)5774 long long NuppelVideoPlayer::CalcCutPointSeek(long long baseframe, bool right) 5401 5775 { 5402 if (seekamount == -2) 5776 QMap<long long, int>::Iterator i = deleteMap.begin(); 5777 long long framenum = -1; 5778 long long seekcount = 0; 5779 if (right) 5403 5780 { 5404 QMap<long long, int>::Iterator i = deleteMap.begin(); 5405 long long framenum = -1; 5406 if (right) 5781 for (; i != deleteMap.end(); ++i) 5407 5782 { 5408 for (; i != deleteMap.end(); ++i)5783 if (i.key() > baseframe) 5409 5784 { 5410 if (i.key() > framesPlayed) 5411 { 5412 framenum = i.key(); 5413 break; 5414 } 5785 framenum = i.key(); 5786 break; 5415 5787 } 5416 if (framenum == -1) 5417 framenum = totalFrames; 5788 } 5789 if (framenum == -1) 5790 framenum = totalFrames; 5791 seekcount = framenum - baseframe; 5792 } 5793 else 5794 { 5795 for (; i != deleteMap.end(); ++i) 5796 { 5797 if (i.key() >= baseframe) 5798 break; 5799 framenum = i.key(); 5800 } 5801 if (framenum == -1) 5802 framenum = 0; 5803 seekcount = baseframe - framenum; 5804 } 5805 return seekcount; 5806 } 5418 5807 5419 fftime = framenum - framesPlayed; 5808 void NuppelVideoPlayer::HandleArbSeek(bool right) 5809 { 5810 if (seekamount == -2) 5811 { 5812 long long seekcount = CalcCutPointSeek(framesPlayed, right); 5813 if (right) 5814 { 5815 fftime = seekcount; 5420 5816 while (fftime > 0) 5421 5817 usleep(1000); 5422 5818 } 5423 5819 else 5424 5820 { 5425 for (; i != deleteMap.end(); ++i) 5426 { 5427 if (i.key() >= framesPlayed) 5428 break; 5429 framenum = i.key(); 5430 } 5431 if (framenum == -1) 5432 framenum = 0; 5433 5434 rewindtime = framesPlayed - framenum; 5821 rewindtime = seekcount; 5435 5822 while (rewindtime > 0) 5436 5823 usleep(1000); 5437 5824 } … … void NuppelVideoPlayer::HandleArbSeek(bo 5462 5849 UpdateEditSlider(); 5463 5850 } 5464 5851 5852 int NuppelVideoPlayer::GetCutStatus(long long testframe) const 5853 { 5854 int retval = 0; 5855 QMap<long long, int>::const_iterator i; 5856 i = deleteMap.find(testframe); 5857 if (i == deleteMap.end()) { 5858 // testframe is not an explicit cutpoint 5859 // See if it is in a deleted area 5860 if (IsInDelete(testframe)) 5861 retval = 1; 5862 } else { 5863 int direction = *i; 5864 if (direction == 0) 5865 retval = 2; 5866 else 5867 retval = 3; 5868 } 5869 5870 return retval; 5871 } 5872 5465 5873 bool NuppelVideoPlayer::IsInDelete(long long testframe) const 5466 5874 { 5467 5875 long long startpos = 0; -
mythtv/libs/libmythtv/NuppelVideoPlayer.h
old new enum 84 84 kDisplayTeletextMenu = 0x40, 85 85 }; 86 86 87 class DeletePointInfo 88 { 89 public: 90 DeletePointInfo() : 91 deleteframe(0), deletepoint(false), cut_after(false), direction(0) {} 92 93 long long deleteframe; 94 bool deletepoint; 95 bool cut_after; 96 int direction; 97 }; 98 87 99 class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 88 100 { 89 101 friend class PlayerContext; 102 friend class GridEditCutpoints; 103 friend class TV; 90 104 91 105 public: 92 106 NuppelVideoPlayer(bool muted = false); … … class MPUBLIC NuppelVideoPlayer : public 279 293 bool EnableEdit(void); 280 294 bool DoKeypress(QKeyEvent *e); 281 295 bool GetEditMode(void) const { return editmode; } 296 bool GetHideEdits(void) const { return hideedits; } 282 297 283 298 // Decoder stuff.. 284 299 VideoFrame *GetNextVideoFrame(bool allow_unsafe = true); … … class MPUBLIC NuppelVideoPlayer : public 298 313 void ShutdownYUVResize(void); 299 314 void SaveScreenshot(void); 300 315 316 // Edit stuff 317 bool EditSeekToFrame(long long targetFrame); 318 void SetScreenGrabSizes(QSize normal, QSize small); 319 bool GetScreenGrabsOfCurrentFrame(QImage & normal, QImage &small); // Get current frame 320 321 void EditHandleClearMap(); 322 void EditHandleInvertMap(); 323 void EditHandleLoadCommSkip(); 324 325 void StartEditRecordingGrid(); 326 void EndEditRecordingGrid(); 327 301 328 // Reinit 302 329 void ReinitOSD(void); 303 330 void ReinitVideo(void); … … class MPUBLIC NuppelVideoPlayer : public 425 452 bool PosMapFromEnc(unsigned long long start, 426 453 QMap<long long, long long> &posMap); 427 454 455 // Stuff for GridEditCutpoints 456 long long CalcCutPointSeek(long long baseframe, bool right); 457 // returns 458 // 0 - no cut 459 // 1 - is deleted 460 // 2 - cut left 461 // 3 - cut right 462 int GetCutStatus(long long testframe) const; 463 long long GetSeekAmount() { return seekamount; } 464 QString GetSeekAmountText() { return seekamounttext; } 465 428 466 protected: 429 467 void DisplayPauseFrame(void); 430 468 void DisplayNormalFrame(void); … … class MPUBLIC NuppelVideoPlayer : public 510 548 void HandleSelect(bool allowSelectNear = false); 511 549 void HandleResponse(void); 512 550 551 DeletePointInfo GetDeletePointInfo(long long frame, bool allowSelectNear); 552 553 void SetupScreenGrab(); 554 void ClearScreenGrab(); 555 513 556 void UpdateTimeDisplay(void); 557 int GetSeekAmountPos() { return seekamountpos; } 514 558 void UpdateSeekAmount(bool up); 559 void SetHalfPageSize(int hp) { allow_pagesize = true; half_page = hp; } 560 void UpdateSeekAmountDisplay(void); 515 561 void UpdateEditSlider(void); 516 562 517 563 // Private A/V Sync Stuff … … class MPUBLIC NuppelVideoPlayer : public 585 631 bool livetv; 586 632 bool watchingrecording; 587 633 bool editmode; 634 bool hideedits; 588 635 bool resetvideo; 589 636 bool using_null_videoout; 590 637 bool no_audio_in; … … class MPUBLIC NuppelVideoPlayer : public 608 655 long long fftime; 609 656 /// 1..9 == keyframe..10 minutes. 0 == cut point 610 657 int seekamountpos; 658 /// Used for Grid Edit logic 659 bool allow_pagesize; 660 int half_page; 611 661 /// Seekable frame increment when not using exact seeks. 612 662 /// Usually equal to keyframedist. 613 663 int seekamount; 664 QString seekamounttext; // OSD seek units 614 665 /// Iff true we ignore seek amount and try to seek to an 615 666 /// exact frame ignoring key frame restrictions. 616 667 bool exactseeks; … … class MPUBLIC NuppelVideoPlayer : public 750 801 QMutex yuv_lock; 751 802 QWaitCondition yuv_wait; 752 803 804 // EditGrid still image capture 805 struct SwsContext *grid_edit_image_scaler; 806 struct SwsContext *grid_edit_image_small_scaler; 807 unsigned char *grid_edit_image_buffer_yuv; 808 unsigned char *grid_edit_image_small_buffer_yuv; 809 unsigned char *grid_edit_image_buffer_rgb; 810 unsigned char *grid_edit_image_small_buffer_rgb; 811 int grid_edit_image_buffer_length; 812 int grid_edit_image_small_buffer_length; 813 QSize grid_edit_image_in_size; 814 QSize grid_edit_image_size; 815 QSize grid_edit_image_small_size; 816 QMutex grid_edit_lock; 817 753 818 // Filters 754 819 QMutex videofiltersLock; 755 820 QString videoFiltersForProgram; -
new file mythbuild/mythtv/libs/libmythtv/grideditcutpoints.cpp
- + 1 #include <math.h> 2 #include <unistd.h> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 #include <QApplication> 8 #include <QPainter> 9 #include <QFont> 10 #include <QKeyEvent> 11 #include <QEvent> 12 #include <QPixmap> 13 #include <QPaintEvent> 14 #include <QCursor> 15 #include <QImage> 16 #include <QLayout> 17 #include <QLabel> 18 #include <QDateTime> 19 #include <QRect> 20 21 #include "mythcontext.h" 22 #include "mythdbcon.h" 23 #include "grideditcutpoints.h" 24 #include "grideditimages.h" 25 #include "NuppelVideoPlayer.h" 26 #include "mythuicutpointbar.h" 27 #include "mythuicutpointimage.h" 28 #include "mythdialogbox.h" 29 #include "tv_play.h" 30 31 #ifndef FUNCTIONLOGGER 32 #define FUNCTIONLOGGER 33 #endif 34 35 void GridEditCutpoints::RunGridEditCutpoints(TV *tv) 36 { 37 FUNCTIONLOGGER; 38 MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack(); 39 40 GridEditCutpoints *er = new GridEditCutpoints(mainStack, "editrecording", tv); 41 42 if (er->Create()) 43 { 44 mainStack->AddScreen(er); 45 } 46 else 47 { 48 VERBOSE(VB_GENERAL, "Create failed"); 49 delete er; 50 } 51 } 52 53 GridEditCutpoints::GridEditCutpoints(MythScreenStack *parent, QString name, TV *tv) 54 : MythScreenType(parent, name, true) 55 { 56 m_tv = tv; 57 58 const PlayerContext *mctx = 59 m_tv->GetPlayerReadLock(0, __FILE__, __LINE__); 60 mctx->LockDeleteNVP(__FILE__, __LINE__); 61 m_player = mctx->nvp; 62 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 63 tv->ReturnPlayerLock(mctx); 64 65 m_images = new GridEditImages(this, m_player); 66 67 } 68 69 GridEditCutpoints::~GridEditCutpoints() 70 { 71 FUNCTIONLOGGER; 72 gContext->removeListener(this); 73 if (m_images) 74 { 75 delete m_images; 76 m_images = NULL; 77 } 78 79 if (m_tv) 80 { 81 QString message = QString("GRIDEDIT_EXITING"); 82 qApp->postEvent(m_tv, new MythEvent(message)); 83 } 84 85 } 86 87 bool GridEditCutpoints::Create() 88 { 89 FUNCTIONLOGGER 90 91 if (!LoadWindowFromXML("recordings-ui.xml", "grideditcutpoints", this)) 92 return false; 93 94 int i; 95 m_gridimagemain = NULL; 96 for (i = m_gridimages.minIndex(); i < m_gridimages.maxIndex(); i++) 97 { 98 m_gridimages[i] = NULL; 99 } 100 101 usedSubVideoCount=0; 102 103 QSize videoSizeMain, videoSizeSmall; 104 105 m_gridimagemain = dynamic_cast<MythUICutPointImage *> (GetChild("mainvideo")); 106 if (m_gridimagemain) 107 videoSizeMain = m_gridimagemain->GetArea().size(); 108 else 109 { 110 VERBOSE(VB_IMPORTANT, "FATAL: Couldn't find grideditcutpoints:mainvideo"); 111 return false; 112 } 113 114 // Small version of main frame 115 m_gridimages[0] = dynamic_cast<MythUICutPointImage *> (GetChild("video0")); 116 117 for (i = 1; i < m_gridimages.maxIndex(); i++) 118 { 119 QString p = QString("videop%1").arg(i); 120 QString m = QString("videom%1").arg(i); 121 122 // Minus frame i 123 m_gridimages[-i] = dynamic_cast<MythUICutPointImage *> (GetChild(m)); 124 if (m_gridimages[-i]) 125 { 126 QSize tmpVideoSizeSmall = m_gridimages[-i]->GetArea().size(); 127 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 128 VERBOSE(VB_IMPORTANT, 129 QString("Multiple sizes found for edit videos (%1)").arg(m)); 130 else 131 videoSizeSmall = tmpVideoSizeSmall; 132 if (i > usedSubVideoCount) usedSubVideoCount=i; 133 } 134 135 m_gridimages[i] = dynamic_cast<MythUICutPointImage *> (GetChild(p)); 136 if (m_gridimages[i]) 137 { 138 QSize tmpVideoSizeSmall = m_gridimages[i]->GetArea().size(); 139 if (videoSizeSmall.isValid() && videoSizeSmall != tmpVideoSizeSmall) 140 VERBOSE(VB_IMPORTANT, 141 QString("Multiple sizes found for edit videos (%1)").arg(p)); 142 else 143 videoSizeSmall = tmpVideoSizeSmall; 144 if (i > usedSubVideoCount) usedSubVideoCount=i; 145 } 146 } 147 148 imageScreenArea = m_gridimages[-usedSubVideoCount]->GetArea(); 149 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 150 if (m_gridimages[i]) 151 imageScreenArea = imageScreenArea.unite(m_gridimages[i]->GetArea()); 152 153 m_slider = dynamic_cast<MythUICutPointBar *> (GetChild("positionbar")); 154 if (!m_slider) 155 VERBOSE(VB_GENERAL, "Missing positionbar for GridEditCutpoints"); 156 else 157 m_slider->InitWidth(); 158 159 // Get Status boxes 160 { 161 m_framenum = dynamic_cast<MythUIText *> (GetChild("framenum")); 162 m_time = dynamic_cast<MythUIText *> (GetChild("time")); 163 m_cutind = dynamic_cast<MythUIText *> (GetChild("cutind")); 164 m_jumpstyle = dynamic_cast<MythUIText *> (GetChild("jumpstyle")); 165 m_updatingind = dynamic_cast<MythUIText *> (GetChild("updatingind")); 166 } 167 168 VERBOSE(VB_GENERAL, QString("main = (%1, %2) small = (%3, %4)") 169 .arg(videoSizeMain.width()).arg(videoSizeMain.height()) 170 .arg(videoSizeSmall.width()).arg(videoSizeSmall.height())); 171 172 slowMotionDirection = 1; // start off play forward 173 slowMotionActive = false; 174 readyForNextFrame = false; 175 slowMotionTimer = NULL; 176 slowMotionTimer = new QTimer(this); 177 QObject::connect(slowMotionTimer, SIGNAL(timeout()), 178 this, SLOT(updateSlowMotion())); 179 180 movingCutpoint = false; 181 // Create blank pixmaps... 182 183 m_images->SetVideoInfo(usedSubVideoCount, videoSizeMain, videoSizeSmall); 184 185 m_player->StartEditRecordingGrid(); 186 187 LoadInBackground(); 188 return true; 189 } 190 191 void GridEditCutpoints::Load() 192 { 193 FUNCTIONLOGGER; 194 } 195 196 void GridEditCutpoints::Init() 197 { 198 FUNCTIONLOGGER; 199 200 // Ensure we're not on keyframe seek 201 202 m_player->SetHalfPageSize(usedSubVideoCount); 203 204 if (m_player->GetSeekAmountPos() == 1) 205 m_player->UpdateSeekAmount(true); 206 207 refreshImages(); 208 refreshCutList(); 209 updateStats(); 210 211 gContext->addListener(this); 212 } 213 214 void GridEditCutpoints::Close() 215 { 216 FUNCTIONLOGGER; 217 218 if (slowMotionTimer) 219 slowMotionTimer->stop(); 220 221 // unsetCursor(); 222 223 m_player->EndEditRecordingGrid(); 224 GetScreenStack()->PopScreen(this, false); 225 } 226 227 void GridEditCutpoints::displayInitialFrame() 228 { 229 refreshImages(); 230 refreshCutList(); 231 updateStats(); 232 } 233 234 void GridEditCutpoints::updateSlowMotion() 235 { 236 if (!slowMotionActive) 237 slowMotionTimer->stop(); 238 else if (readyForNextFrame && slowMotionDirection != 0) 239 { 240 readyForNextFrame=false; 241 242 if (slowMotionDirection > 0) 243 EditHandleRight(); 244 else if (slowMotionDirection < 0) 245 EditHandleLeft(); 246 } 247 } 248 249 250 void GridEditCutpoints::setSlowMotionSpeed() 251 { 252 // slowMotionDirection is max FPS 253 254 if (slowMotionDirection != 0) 255 { 256 int smd = slowMotionDirection; 257 if (smd < 0) smd = -smd; 258 int timeout = 1000 / smd; 259 260 slowMotionTimer->start(timeout); 261 } 262 SetUpdating(true, QString("%1 FPS max").arg(slowMotionDirection)); 263 } 264 265 266 bool GridEditCutpoints::keyPressEvent(QKeyEvent *event) 267 { 268 FUNCTIONLOGGER; 269 270 QStringList actions; 271 bool handled = false; 272 handled = GetMythMainWindow()->TranslateKeyPress("TV Editing", event, actions); 273 274 if (handled) 275 return true; 276 277 bool skipMost=false; 278 279 for (unsigned int i = 0; i < actions.size() && !handled; i++) 280 { 281 QString action = actions[i]; 282 handled = true; 283 284 VERBOSE(VB_GENERAL, QString("key[%1] = '%2'").arg(i).arg(action)); 285 286 if (action == "SELECT" && !skipMost) 287 { 288 if (slowMotionActive) 289 stopSlowMotion(); 290 else if (movingCutpoint) 291 { 292 // Move cutpoint 293 m_player->DeleteMark(savedCutpoint); 294 m_player->AddMark(m_images->GetCurrentFrameNumber(), savedCutType); 295 movingCutpoint = false; 296 refreshCutList(); 297 refreshImages(); 298 } 299 else 300 handleSelect(); 301 } 302 else if (action == "PAUSE" && !skipMost) 303 stopSlowMotion(); 304 else if (action == "SLOWMO" && !skipMost) 305 { 306 if (movingCutpoint) 307 ShowOkPopup("Slow Motion Unavailable when moving cutpoint"); 308 else 309 { 310 if (slowMotionActive) 311 stopSlowMotion(); 312 else 313 startSlowMotion(); 314 } 315 } 316 else if (action == "LEFT" && !skipMost) 317 { 318 if (slowMotionActive) 319 { 320 slowMotionDirection--; 321 setSlowMotionSpeed(); 322 } 323 else 324 EditHandleLeft(); 325 } 326 else if (action == "RIGHT" && !skipMost) 327 { 328 if (slowMotionActive) 329 { 330 slowMotionDirection++; 331 setSlowMotionSpeed(); 332 } 333 else 334 EditHandleRight(); 335 } 336 else if (action == "UP" && !skipMost) 337 { 338 m_player->UpdateSeekAmount(true); 339 updateStats(); 340 } 341 else if (action == "DOWN" && !skipMost) 342 { 343 if (slowMotionActive && m_player->GetSeekAmountPos() == 2) 344 ShowOkPopup("CutPoint skip Unavailable in Slow Motion"); 345 else 346 { 347 m_player->UpdateSeekAmount(false); 348 updateStats(); 349 } 350 } 351 else if (action == "CLEARMAP" && !skipMost) 352 { 353 if (movingCutpoint) 354 ShowOkPopup("Clear Cut Map Unavailable when Moving Cutpoint"); 355 else if (slowMotionActive) 356 ShowOkPopup("Clear Cut Map Unavailable in Slow Motion"); 357 else 358 { 359 SetUpdating(true); 360 m_player->EditHandleClearMap(); 361 refreshCutList(); 362 updateStats(); 363 SetUpdating(false); 364 } 365 } 366 else if (action == "INVERTMAP" && !skipMost) 367 { 368 if (movingCutpoint) 369 ShowOkPopup("Invert Cut Map Unavailable when Moving Cutpoint"); 370 else if (slowMotionActive) 371 ShowOkPopup("Invert Cut Map Unavailable in Slow Motion"); 372 else 373 { 374 SetUpdating(true); 375 m_player->EditHandleInvertMap(); 376 refreshCutList(); 377 updateStats(); 378 SetUpdating(false); 379 } 380 } 381 else if (action == "LOADCOMMSKIP" && !skipMost) 382 { 383 if (movingCutpoint) 384 ShowOkPopup("Load Comm Skip Map Unavailable when Moving Cutpoint"); 385 else if (slowMotionActive) 386 ShowOkPopup("Load Comm Skip Map Unavailable in Slow Motion"); 387 else 388 { 389 SetUpdating(true); 390 m_player->EditHandleLoadCommSkip(); 391 refreshCutList(); 392 updateStats(); 393 SetUpdating(false); 394 } 395 } 396 else if (action == "PREVCUT" && !skipMost) 397 { 398 if (slowMotionActive) 399 ShowOkPopup("Prev Cut Unavailable in Slow Motion"); 400 else 401 EditHandlePrevCut(); 402 } 403 else if (action == "NEXTCUT" && !skipMost) 404 { 405 if (slowMotionActive) 406 ShowOkPopup("Next Cut Unavailable in Slow Motion"); 407 else 408 EditHandleNextCut(); 409 } 410 else if (action == "BIGJUMPREW" && !skipMost) 411 EditHandleBigJumpRew(); 412 else if (action == "BIGJUMPFWD" && !skipMost) 413 EditHandleBigJumpFwd(); 414 else if (action == "ESCAPE" && movingCutpoint) 415 { 416 movingCutpoint = false; 417 SetUpdating(false); 418 } 419 else if (action == "ESCAPE" && slowMotionActive) 420 stopSlowMotion(); 421 else if (action == "ESCAPE" || action == "TOGGLEEDIT" || 422 action == "MENU") 423 Close(); 424 else 425 handled = false; 426 427 if (movingCutpoint) 428 SetUpdating(true, "Moving Cutpoint"); 429 } 430 431 if (!handled && MythScreenType::keyPressEvent(event)) 432 handled = true; 433 434 return handled; 435 } 436 437 void GridEditCutpoints::customEvent(QEvent *event) 438 { 439 FUNCTIONLOGGER; 440 bool needupdate = false; 441 442 VERBOSE(VB_GENERAL, QString("Got Event %1").arg(event->type())); 443 444 if (event->type() == DialogCompletionEvent::kEventType) 445 { 446 DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); 447 448 QString resultid = dce->GetId(); 449 QString resulttext = dce->GetResultText(); 450 int buttonnum = dce->GetResult(); 451 452 VERBOSE(VB_GENERAL, QString("Got '%1' '%2' %3") 453 .arg(resultid).arg(resulttext).arg(buttonnum)); 454 455 if (resultid == "cutpointexists") 456 { 457 FrameStats fs = m_images->GetMainFrameStats(); 458 // menuPopup->AddButton("Delete cutpoint?"); 459 // menuPopup->AddButton("Move cutpoint?"); 460 // if (fs.cutInd == 2) 461 // menuPopup->AddButton("Flip directions (Cut After)?"); 462 // else 463 // menuPopup->AddButton("Flip directions (Cut Before)?"); 464 465 if (resulttext == "Delete cutpoint?") 466 { 467 m_player->DeleteMark(fs.frameNumber); 468 needupdate = true; 469 } 470 else if (resulttext == "Move cutpoint?") 471 { 472 // Move cutpoint 473 savedCutpoint = fs.frameNumber; 474 savedCutType = m_player->deleteMap[fs.frameNumber]; 475 movingCutpoint = true; 476 // Ensure we're at least at 1 frame motion 477 int i; 478 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 479 m_player->UpdateSeekAmount(true); 480 needupdate = true; 481 } 482 else if (resulttext == "Flip directions (Cut After)?" || 483 resulttext == "Flip directions (Cut Before)?") 484 { 485 m_player->ReverseMark(fs.frameNumber); 486 needupdate = true; 487 } 488 } 489 else if (resultid == "addcutpoint") 490 { 491 FrameStats fs = m_images->GetMainFrameStats(); 492 // menuPopup->AddButton("Delete before this frame"); 493 // menuPopup->AddButton("Delete after this frame"); 494 495 if (resulttext == "Delete before this frame") 496 { 497 // Delete left 498 m_player->AddMark(fs.frameNumber, MARK_CUT_END); 499 needupdate = true; 500 } 501 else if (resulttext == "Delete after this frame") 502 { 503 // Delete Right 504 m_player->AddMark(fs.frameNumber, MARK_CUT_START); 505 needupdate = true; 506 } 507 } 508 509 } else 510 MythScreenType::customEvent(event); 511 512 if (needupdate) 513 { 514 refreshCutList(); 515 refreshImages(); 516 } 517 } 518 519 void GridEditCutpoints::startSlowMotion() 520 { 521 if (!slowMotionActive) 522 { 523 slowMotionActive = true; 524 readyForNextFrame = true; 525 slowMotionDirection = 1; 526 527 // force to either 1 frame. 1/2 page or full page motion 528 int i; 529 // move to 1 frame if on cutpoint 530 for (i = 0; m_player->GetSeekAmountPos() < 2 && i < 10; i++) 531 m_player->UpdateSeekAmount(true); 532 533 // move to fullpage if higher 534 for (i = 0; m_player->GetSeekAmountPos() > 4 && i < 10; i++) 535 m_player->UpdateSeekAmount(false); 536 537 setSlowMotionSpeed(); 538 } 539 } 540 541 void GridEditCutpoints::stopSlowMotion() 542 { 543 if (slowMotionActive) 544 { 545 slowMotionActive = false; 546 slowMotionTimer->stop(); 547 SetUpdating(false); 548 } 549 } 550 551 552 void GridEditCutpoints::EditHandleLeft(int seektype) 553 { 554 long long seekamount = m_player->GetSeekAmount(); 555 bool cutpointseek = false; 556 557 if (seektype == -2 || seekamount == -2) 558 cutpointseek = true; 559 else 560 { 561 // seektype == 1 for normal, 10 for bigjump 562 seekamount *= seektype; 563 } 564 565 if (seekamount < 0) // Invalid -- keyframe 566 seekamount = 1; 567 568 m_images->SeekLeft(seekamount, cutpointseek); 569 570 refreshImages(); 571 updateStats(); 572 } 573 574 void GridEditCutpoints::EditHandleRight(int seektype) 575 { 576 long long seekamount = m_player->GetSeekAmount(); 577 bool cutpointseek=false; 578 579 if (seektype == -2 || seekamount == -2) 580 cutpointseek = true; 581 else 582 { 583 // seektype == 1 for normal, 10 for bigjump 584 seekamount *= seektype; 585 } 586 587 if (seekamount < 0) // Invalid -- keyframe 588 seekamount = 1; 589 590 m_images->SeekRight(seekamount, cutpointseek); 591 592 refreshImages(); 593 updateStats(); 594 } 595 596 void GridEditCutpoints::handleSelect(void) 597 { 598 bool needupdate = false; 599 // add / update cutpoint 600 // -or- 601 // delete / flip / move cutpoint 602 603 // if no cut points on screen 604 // "Delete Before" 605 // "Delete After" 606 607 // if on existing cutpoint 608 // "Delete cutpoint" 609 // "Flip directions" 610 611 // FIXME 612 // if a cutpoint exists on the screen but not on the current frame 613 // "Move to current frame" 614 // "Add new" 615 616 FrameStats fs = m_images->GetMainFrameStats(); 617 DeletePointInfo dpi = m_player->GetDeletePointInfo(fs.frameNumber, true); 618 619 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); 620 621 if (fs.cutInd >= 2) 622 { 623 MythDialogBox *menuPopup = new MythDialogBox("Cutpoint Exists", popupStack, "menuPopup"); 624 if (menuPopup->Create()) 625 { 626 menuPopup->SetReturnEvent(this, "cutpointexists"); 627 628 menuPopup->AddButton("Delete cutpoint?", 0, false, true); // Default 629 menuPopup->AddButton("Move cutpoint?"); 630 if (fs.cutInd == 2) 631 menuPopup->AddButton("Flip directions (Cut After)?"); 632 else 633 menuPopup->AddButton("Flip directions (Cut Before)?"); 634 635 popupStack->AddScreen(menuPopup); 636 } 637 else 638 { 639 delete menuPopup; 640 } 641 } 642 else 643 { 644 MythDialogBox *menuPopup = new MythDialogBox("Insert New Cutpoint?", popupStack, "menuPopup"); 645 if (menuPopup->Create()) 646 { 647 menuPopup->SetReturnEvent(this, "addcutpoint"); 648 649 menuPopup->AddButton("Delete before this frame"); 650 menuPopup->AddButton("Delete after this frame", 0, false, dpi.cut_after); // might be default 651 652 popupStack->AddScreen(menuPopup); 653 } 654 else 655 { 656 delete menuPopup; 657 } 658 } 659 } 660 661 void GridEditCutpoints::refreshImages() 662 { 663 m_images->refreshImages(m_gridimagemain, m_gridimages, false); 664 // repaint(m_gridimagemain->GetArea()); 665 // repaint(imageScreenArea); 666 } 667 668 void GridEditCutpoints::refreshCutList() 669 { 670 m_images->refreshCutList(m_gridimagemain, m_gridimages); 671 refreshSlider(); 672 } 673 674 void GridEditCutpoints::refreshSlider() 675 { 676 if (!m_slider) 677 return; 678 679 m_slider->ClearAll(); 680 681 const int CUT_LEFT = 0; 682 const int CUT_RIGHT = 1; 683 684 long long startpos = 0; 685 long long endpos = 0; 686 687 int lastdirection = CUT_LEFT; 688 689 QMap<long long, int> & deleteMap = m_player->deleteMap; 690 QMap<long long, int>::Iterator i = deleteMap.begin(); 691 for (; i != deleteMap.end(); ++i) 692 { 693 long long frame = i.key(); 694 int direction = *i; 695 696 if (direction == CUT_LEFT) 697 { 698 endpos = frame; 699 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 700 701 startpos = frame; 702 lastdirection = CUT_LEFT; 703 } 704 else if (direction == CUT_RIGHT) 705 { 706 if (lastdirection == CUT_RIGHT) 707 { 708 // continuing within a cutpoint 709 endpos = frame; 710 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 711 } 712 713 startpos = frame; 714 lastdirection = CUT_RIGHT; 715 } 716 } 717 718 if (lastdirection == CUT_RIGHT) 719 { 720 // continuing within a cutpoint 721 endpos = m_images->GetMaxFrameNumber(); 722 m_slider->SetRange(startpos, endpos, m_images->GetMaxFrameNumber()); 723 } 724 } 725 726 void GridEditCutpoints::updateStats(bool forcerepaint) 727 { 728 FUNCTIONLOGGER; 729 int secs, frames, ss, mm, hh; 730 731 FrameStats fs = m_images->GetMainFrameStats(); 732 733 secs = (int)(fs.frameNumber / m_player->GetFrameRate()); 734 frames = fs.frameNumber - (int)(secs * m_player->GetFrameRate()); 735 736 ss = secs; 737 mm = ss / 60; 738 ss %= 60; 739 hh = mm / 60; 740 mm %= 60; 741 742 char timestr[128]; 743 sprintf(timestr, "%d:%02d:%02d.%02d", hh, mm, ss, frames); 744 745 char framestr[128]; 746 sprintf(framestr, "%lld", fs.frameNumber); 747 748 if (m_time) 749 { 750 m_time->SetText(timestr); 751 // if (forcerepaint) 752 // repaint(m_time->getScreenArea()); 753 } 754 if (m_framenum) 755 { 756 m_framenum->SetText(framestr); 757 // if (forcerepaint) 758 // repaint(m_framenum->getScreenArea()); 759 } 760 if (m_cutind) 761 { 762 switch (fs.cutInd) { 763 case 0: m_cutind->SetText(""); break; 764 case 1: m_cutind->SetText("Cut"); break; 765 case 2: m_cutind->SetText("Cut Before"); break; 766 case 3: m_cutind->SetText("Cut After"); break; 767 } 768 // if (forcerepaint) 769 // repaint(m_cutind->getScreenArea()); 770 } 771 772 // Don't need to force update this 773 if (m_jumpstyle) 774 m_jumpstyle->SetText(m_player->GetSeekAmountText()); 775 776 if (m_slider) 777 m_slider->SetCurrentPosition(fs.frameNumber, fs.maxFrameNumber); 778 779 } 780 781 void GridEditCutpoints::escape() 782 { 783 // Make sure we're on the right frame when we go back to 784 // Normal edit mode 785 // unsetCursor(); 786 // accept(); 787 } 788 789 void GridEditCutpoints::displayCacheStatus(int level) 790 { 791 // 0 - onscreen frames 792 // 1 - precache frames 793 // 2 - fill-out-the buffer frames 794 795 if (!slowMotionActive && !movingCutpoint) 796 switch (level) { 797 case 0: SetUpdating(true, "Displaying"); break; 798 case 1: SetUpdating(true, "Pre-Caching"); break; 799 case 2: SetUpdating(true, "Caching"); break; 800 default: SetUpdating(false); 801 } 802 } 803 804 void GridEditCutpoints::SetUpdating(bool active, QString text) 805 { 806 807 if (m_updatingind) 808 { 809 //VERBOSE(VB_GENERAL, QString("Updating to %1").arg(active)); 810 if (active) 811 { 812 m_updatingind->Show(); 813 m_updatingind->SetText(text); 814 } 815 else 816 m_updatingind->Hide(); 817 // repaint(m_updatingind->getScreenArea()); 818 } 819 } 820 821 void GridEditCutpoints::cacheFramesAreReady() 822 { 823 if (slowMotionActive) 824 { 825 readyForNextFrame=true; 826 if (!slowMotionTimer->isActive()) 827 slowMotionTimer->start(0); 828 } 829 } 830 -
new file mythbuild/mythtv/libs/libmythtv/grideditcutpoints.h
- + 1 // -*- Mode: c++ -*- 2 #ifndef GRIDEDITCUTPOINTS_H_ 3 #define GRIDEDITCUTPOINTS_H_ 4 5 #include <QObject> 6 #include <QEvent> 7 8 //#include "libmyth/mythwidgets.h" 9 //#include "uitypes.h" 10 11 #include "mythscreentype.h" 12 #include "grideditimages.h" 13 14 15 class QTimer; 16 class NuppelVideoPlayer; 17 class GridEditImages; 18 class MythUICutPointBar; 19 class MythUICutPointImage; 20 class MythUIText; 21 class TV; 22 23 class GridEditCutpoints : public MythScreenType 24 { 25 Q_OBJECT 26 public: 27 // Use this function to instantiate an GridEditCutpoints instance. 28 static void RunGridEditCutpoints(TV *tv); 29 30 void refreshImages(); 31 void cacheFramesAreReady(); 32 bool isValid() { return ((usedSubVideoCount > 0) && (m_gridimagemain != NULL)); }; 33 void displayCacheStatus(int level); 34 35 GridEditCutpoints(MythScreenStack *parent, QString name, TV *tv); 36 ~GridEditCutpoints(); 37 38 bool Create(void); 39 virtual void Load(void); 40 virtual void Init(void); 41 virtual void Close(void); 42 43 protected: 44 void displayInitialFrame(); 45 46 void handleSelect(); 47 48 void updateStats(bool forcerepaint = false); 49 50 void startSlowMotion(); 51 void stopSlowMotion(); 52 53 protected slots: 54 void escape(); 55 void updateSlowMotion(); 56 57 void customEvent(QEvent *event); 58 59 private: 60 bool keyPressEvent(QKeyEvent *e); 61 62 // seektype == -2 - cutpoint seek 63 // seektype == 1 - normal seek 64 // seektype == 10 - large seek 65 void EditHandleLeft(int seektype = 1); 66 void EditHandleRight(int seektype = 1); 67 void EditHandlePrevCut() { EditHandleLeft(-2); }; 68 void EditHandleNextCut() { EditHandleRight(-2); }; 69 void EditHandleBigJumpRew() { EditHandleLeft(10); }; 70 void EditHandleBigJumpFwd() { EditHandleRight(10); }; 71 void setSlowMotionSpeed(); 72 void refreshCutList(); 73 void refreshSlider(); 74 75 void SetUpdating(bool active, QString text = "Updating"); 76 77 // Private Data 78 79 NuppelVideoPlayer *m_player; 80 TV *m_tv; 81 GridEditImages *m_images; 82 83 int usedSubVideoCount; 84 myArray<MythUICutPointImage*, MAX_SUB_VIDEOS> m_gridimages; 85 // The main Big image 86 MythUICutPointImage* m_gridimagemain; 87 88 long long savedCutpoint; 89 int savedCutType; 90 bool movingCutpoint; 91 92 MythUIText *m_framenum; 93 MythUIText *m_time; 94 MythUIText *m_cutind; 95 MythUIText *m_jumpstyle; 96 MythUIText *m_updatingind; 97 98 MythUICutPointBar *m_slider; 99 QTimer *slowMotionTimer; 100 int slowMotionDirection; 101 bool slowMotionActive; 102 bool readyForNextFrame; 103 104 QRect imageScreenArea; 105 }; 106 107 #endif -
new file mythbuild/mythtv/libs/libmythtv/grideditimages.cpp
- + 1 #include <math.h> 2 #include <unistd.h> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 #include <QApplication> 8 #include <QPainter> 9 #include <QFont> 10 #include <QKeyEvent> 11 #include <QEvent> 12 #include <QPixmap> 13 #include <QPaintEvent> 14 #include <QCursor> 15 #include <QImage> 16 #include <QLayout> 17 #include <QLabel> 18 #include <QDateTime> 19 #include <QRect> 20 21 #include "mythcontext.h" 22 #include "mythdbcon.h" 23 #include "grideditimages.h" 24 #include "grideditcutpoints.h" 25 #include "NuppelVideoPlayer.h" 26 #include "mythuicutpointimage.h" 27 28 #define FRAME_DEBUG 0 29 #define CACHE_DEBUG 0 30 31 #ifndef FUNCTIONLOGGER 32 #define FUNCTIONLOGGER 33 #endif 34 35 36 GridEditImages::GridEditImages(GridEditCutpoints *editor, NuppelVideoPlayer *player) 37 { 38 m_editor = editor; 39 m_player = player; 40 usedSubVideoCount = 0; 41 42 lastmovewasright= true; 43 44 int i; 45 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 46 { 47 stillFrames[i] = NULL; 48 stillFramesBig[i] = NULL; 49 cutFrames[i] = 0; 50 } 51 52 memset(cutFramesCache, 0, sizeof(cutFramesCache)); 53 memset(stillFramesCache, 0, sizeof(stillFramesCache)); 54 memset(stillFramesBigCache, 0, sizeof(stillFramesBigCache)); 55 stillFrameCacheCount = 0; 56 stillFramesCacheBase = 0; 57 58 // Get first frames... 59 stillMainFrameNumber = m_player->GetFramesPlayed(); 60 if (stillMainFrameNumber <= 0) 61 stillMainFrameNumber = 1; 62 63 // maxFrameNumber may be overridden if neccessary 64 maxFrameNumber = m_player->GetTotalFrameCount(); 65 maxFrameNumberNVP = m_player->GetTotalFrameCount(); 66 67 if (stillMainFrameNumber <= 0) 68 stillMainFrameNumber = 1; 69 70 if (stillMainFrameNumber > maxFrameNumber) 71 stillMainFrameNumber = maxFrameNumber; 72 73 getImagesTimer = new QTimer(this); 74 QObject::connect(getImagesTimer, SIGNAL(timeout()), 75 this, SLOT(updateAllFrames())); 76 77 78 } 79 80 GridEditImages::~GridEditImages() 81 { 82 emptyCache(); 83 clearStillFrames(); 84 m_player->EditSeekToFrame(stillMainFrameNumber); 85 } 86 87 QPixmap *GridEditImages::makeScaledPixmap(const QImage& qim, QSize sz) 88 { 89 QPixmap *retval; 90 if (qim.size() == sz) 91 { 92 retval = new QPixmap(sz); 93 QPainter p(retval); 94 p.drawImage(0, 0, qim); 95 } 96 else 97 { 98 retval = new QPixmap(sz); 99 retval->fill(Qt::black); 100 QPainter p(retval); 101 102 int tl_left = 0; 103 int tl_top = 0; 104 if (sz.width() > qim.width()) 105 tl_left += (sz.width() - qim.width()) / 2; 106 107 if (sz.height() > qim.height()) 108 tl_top += (sz.height() - qim.height()) / 2; 109 110 // VERBOSE(VB_GENERAL, QString("Size mismatch qim(%1, %2) != sz(%3, %4) Shift to (%5, %6)") 111 // .arg(qim.width()).arg(qim.height()) 112 // .arg(sz.width()).arg(sz.height()) 113 // .arg(tl_left).arg(tl_top)); 114 115 p.drawImage(tl_left, tl_top, qim); 116 } 117 return retval; 118 } 119 120 void GridEditImages::getMainStillFrame() 121 { 122 getSpecificFrame(0); 123 } 124 125 bool GridEditImages::getFrameIndexes(int newlevel) 126 { 127 // levels: 128 // 0 - onscreen frames 129 // 1 - precache frames 130 // 2 - fill-out-the buffer frames 131 132 m_editor->displayCacheStatus(newlevel); 133 if (newlevel > 2) 134 return false; 135 136 // This gets the upper and lower indexes of the frames we need to get. 137 // Note these indexes maybe negative 138 // Negative frames are before the main frame 139 // Frame #0 is the main frame 140 // Positive frames are after the main frame 141 142 // Basic initialization 143 // Doesn't go to absolute end because it slows down seeking 144 // when you go 1 frame left and right 145 frameIndexLeft = stillFrames.minIndex() + 4; 146 frameIndexRight = stillFrames.maxIndex() - 4; 147 getFutureFramesFirst = false; 148 149 if (newlevel == 0) // Current Display only 150 { 151 frameIndexLeft = -usedSubVideoCount; 152 frameIndexRight = usedSubVideoCount; 153 } 154 else 155 { 156 getFutureFramesFirst = lastmovewasright; 157 158 if (newlevel == 1) // PreCache only 159 { 160 // preCacheIndexLeft and Right are indexes for the frames to start and end on 161 frameIndexLeft = preCacheIndexLeft; 162 frameIndexRight = preCacheIndexRight; 163 } 164 } 165 166 // Make sure we don't fall of the front of the file 167 if (stillMainFrameNumber + frameIndexLeft <= 0) 168 frameIndexLeft = -(stillMainFrameNumber-1); 169 170 // ... or the back of the file 171 if (frameIndexRight > (maxFrameNumber - stillMainFrameNumber)) 172 frameIndexRight = (maxFrameNumber - stillMainFrameNumber); 173 174 #if CACHE_DEBUG 175 VERBOSE(VB_GENERAL, QString("Getting frames from %1 to %2 for level %3") 176 .arg(frameIndexLeft).arg(frameIndexRight).arg(newlevel)); 177 #endif 178 return true; 179 } 180 181 bool GridEditImages::getStillFrames(int maxcount) 182 { 183 // returns true if no more frames to get 184 185 // This will fill in all the missing frames in the cache 186 187 long long i; 188 if (getFutureFramesFirst && frameIndexLeft < 0) 189 { 190 // If we're filling out the cache and the last move was to the right 191 // grab future frames first before any past frames 192 for (i = 1; i <= frameIndexRight; i++) 193 if (getSpecificFrame(i)) 194 if (--maxcount == 0) return false; 195 } 196 197 // grab all appropriate frames 198 199 for (i = frameIndexLeft; i <= frameIndexRight; i++) 200 if (getSpecificFrame(i)) 201 if (--maxcount == 0) return false; 202 203 return true; 204 } 205 206 bool GridEditImages::getSpecificFrame(long long i) 207 { 208 // i is the index within the cache of frames 209 210 // If we're outside of the normal boundaries of the buffer, 211 // see if we've precached this frame 212 if (i < stillFrames.minIndex() || i > stillFrames.maxIndex()) 213 { 214 // First extra cached frame 215 if (stillFrameCacheCount == 0) 216 stillFramesCacheBase = stillMainFrameNumber + i; 217 218 int tmpi; 219 for (tmpi = 0; tmpi < stillFrameCacheCount; tmpi++) 220 { 221 long long tmpframe = (stillFramesCacheBase + tmpi); 222 if (tmpframe == stillMainFrameNumber + i) 223 return false; 224 } 225 226 // Check for cache overflow 227 if (stillFrameCacheCount >= MAX_SUB_VIDEOS) 228 { 229 VERBOSE(VB_GENERAL, QString("Cached too many videos. Max = %1").arg(MAX_SUB_VIDEOS)); 230 return false; 231 } 232 233 tmpi = stillFrameCacheCount++; 234 235 #if CACHE_DEBUG 236 VERBOSE(VB_GENERAL, QString("Caching frame %1, (frm# %2, index %3)") 237 .arg(tmpi).arg(stillMainFrameNumber + i) 238 .arg(i)); 239 #endif 240 241 getFrame(i, cutFramesCache[tmpi], stillFramesCache[tmpi], stillFramesBigCache[tmpi]); 242 return true; 243 } 244 else if (!stillFrames[i]) 245 { 246 getFrame(i, cutFrames[i], stillFrames[i], stillFramesBig[i]); 247 return true; 248 } 249 250 return false; 251 } 252 253 void GridEditImages::getFrame(long long i, 254 int &cutFrame, 255 QPixmap * &stillFrame, 256 QPixmap * &stillFrameBig) 257 { 258 // get this frame 259 long long targetFrame = stillMainFrameNumber + i; 260 261 if (!m_player->EditSeekToFrame(targetFrame)) 262 { 263 VERBOSE(VB_GENERAL, QString("Error seeking to Frame[%1] (frame # %2)") 264 .arg(i).arg(targetFrame)); 265 checkMaxFrameCount(); 266 267 stillFrameBig = new QPixmap(videoSizeMain); 268 stillFrameBig->fill(Qt::gray); 269 270 stillFrame = new QPixmap(videoSizeSmall); 271 stillFrame->fill(Qt::gray); 272 } 273 else 274 { 275 cutFrame = m_player->GetCutStatus(targetFrame); 276 QImage normal, small; 277 m_player->GetScreenGrabsOfCurrentFrame(normal, small); 278 279 stillFrameBig = makeScaledPixmap(normal, videoSizeMain); 280 stillFrame = makeScaledPixmap(small, videoSizeSmall); 281 282 #if FRAME_DEBUG 283 VERBOSE(VB_GENERAL, QString("stillFrames[%1] = %2 (%3)") 284 .arg(i) 285 .arg(targetFrame) 286 .arg(cutFrame)); 287 #endif 288 } 289 } 290 291 void GridEditImages::SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall) 292 { 293 usedSubVideoCount = vcount; 294 videoSizeMain = sizeMain; 295 videoSizeSmall = sizeSmall; 296 SetPreCache(1); 297 298 m_player->SetScreenGrabSizes(videoSizeMain, videoSizeSmall); 299 300 // start to grab the current images 301 getMainStillFrame(); 302 startFrameCaching(); 303 } 304 305 void GridEditImages::startFrameCaching() 306 { 307 frameCacheLevel=0; 308 getFrameIndexes(frameCacheLevel); 309 310 getImagesTimer->start(0); 311 } 312 313 void GridEditImages::SetPreCache(long long pccount) 314 { 315 preCacheIndexLeft = pccount - usedSubVideoCount; 316 preCacheIndexRight = pccount + usedSubVideoCount; 317 } 318 319 void GridEditImages::updateAllFrames() 320 { 321 // getStillFrames() returns 'true' on the next call after it's gotten all requested frames 322 323 if (getStillFrames(1)) 324 { 325 // If we've pre-cached the next screen of frames, tell the editor about it 326 if (frameCacheLevel == 1) 327 m_editor->cacheFramesAreReady(); 328 329 frameCacheLevel++; 330 if (getFrameIndexes(frameCacheLevel)) 331 getStillFrames(1); 332 else 333 stopFrameCaching(); 334 } 335 m_editor->refreshImages(); 336 } 337 338 void GridEditImages::clearStillFrames() 339 { 340 int i; 341 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 342 { 343 if (stillFrames[i]) 344 { 345 delete stillFrames[i]; 346 stillFrames[i] = NULL; 347 } 348 if (stillFramesBig[i]) 349 { 350 delete stillFramesBig[i]; 351 stillFramesBig[i] = NULL; 352 } 353 cutFrames[i] = 0; 354 } 355 } 356 357 bool GridEditImages::shiftStillFramesLeft(long long offset) 358 { 359 if (offset > 2 * stillFrames.maxIndex()) 360 { 361 // Dump all cached data and re-get it 362 clearStillFrames(); 363 } 364 else if (offset < 0) 365 { 366 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 367 // Dump all cached data and re-get it 368 clearStillFrames(); 369 offset = 0; 370 } 371 else if (offset != 0) 372 { 373 // Shift backwards in the stream by offset 374 375 // All frames will actually shift to the right. 376 // frame 'n' will become frame 'n+1' 377 // frame stillFrameMinus[1] will become mainframe 378 // frame stillFramePlus[max] will drop off 379 380 // shove extra frames into the excess space above usedSubVideos 381 382 if (offset >= stillMainFrameNumber) 383 offset = (stillMainFrameNumber-1); 384 385 // printStillFrameStats("Before SL"); 386 int i,j; 387 int minIndex = stillFrames.minIndex(); 388 int maxIndex = stillFrames.maxIndex(); 389 for (i = 0; i < offset; i++) 390 { 391 392 if (stillFrames[maxIndex]) 393 { 394 delete stillFrames[maxIndex]; 395 delete stillFramesBig[maxIndex]; 396 } 397 398 for (j = maxIndex; j > minIndex; j--) { 399 stillFrames[j] = stillFrames[j-1]; 400 stillFramesBig[j] = stillFramesBig[j-1]; 401 cutFrames[j] = cutFrames[j-1]; 402 } 403 404 stillFrames[minIndex] = NULL; 405 stillFramesBig[minIndex] = NULL; 406 cutFrames[minIndex] = 0; 407 } 408 409 // printStillFrameStats("After SL"); 410 411 } 412 413 stillMainFrameNumber -= offset; 414 if (stillMainFrameNumber < 1) 415 stillMainFrameNumber = 1; 416 417 emptyCache(); 418 419 return (stillFramesBig[0] != NULL); 420 } 421 422 bool GridEditImages::shiftStillFramesRight(long long offset) 423 { 424 //VERBOSE(VB_GENERAL, QString("Offset = %1").arg(offset)); 425 if (offset > 2 * stillFrames.maxIndex()) 426 { 427 // Dump all cached data and re-get it 428 clearStillFrames(); 429 } 430 else if (offset < 0) 431 { 432 VERBOSE(VB_IMPORTANT, QString("Offset (%1) < 0").arg(offset)); 433 // Dump all cached data and re-get it 434 clearStillFrames(); 435 offset = 0; 436 } 437 else if (offset != 0) 438 { 439 440 // Shift forwards in the stream by offset 441 442 // All frames will actually shift to the left. 443 // frame 'n' will become frame 'n-1' 444 // frame stillFramePlus[1] will become mainframe 445 // frame stillFrameMinus[max] will drop off 446 447 // shove extra frames into the excess space above usedSubVideos 448 449 if (stillMainFrameNumber + offset > maxFrameNumber) 450 { 451 offset = (maxFrameNumber - stillMainFrameNumber); 452 VERBOSE(VB_GENERAL, QString("new Offset = %1").arg(offset)); 453 } 454 //printStillFrameStats("Before SR"); 455 456 int i,j; 457 int minIndex = stillFrames.minIndex(); 458 int maxIndex = stillFrames.maxIndex(); 459 460 for (i = 0; i < offset; i++) 461 { 462 if (stillFrames[minIndex]) 463 { 464 delete stillFrames[minIndex]; 465 delete stillFramesBig[minIndex]; 466 } 467 468 for (j = minIndex; j < maxIndex; j++) { 469 stillFrames[j] = stillFrames[j+1]; 470 stillFramesBig[j] = stillFramesBig[j+1]; 471 cutFrames[j] = cutFrames[j+1]; 472 } 473 474 stillFrames[maxIndex] = NULL; 475 stillFramesBig[maxIndex] = NULL; 476 cutFrames[maxIndex] = 0; 477 } 478 479 //printStillFrameStats("After SR"); 480 481 } 482 stillMainFrameNumber += offset; 483 if (stillMainFrameNumber > maxFrameNumber ) 484 stillMainFrameNumber = maxFrameNumber; 485 486 emptyCache(); 487 488 return (stillFramesBig[0] != NULL); 489 } 490 491 void GridEditImages::emptyCache() 492 { 493 #if CACHE_DEBUG 494 if (stillFrameCacheCount > 0) 495 { 496 long long minindex = (stillFramesCacheBase - stillMainFrameNumber); 497 long long maxindex = (stillFramesCacheBase+stillFrameCacheCount-1) - stillMainFrameNumber; 498 VERBOSE(VB_GENERAL, QString("emptying %1 frames (%2 - %3) into [%4] - [%5] ") 499 .arg(stillFrameCacheCount) 500 .arg(stillFramesCacheBase) 501 .arg(stillFramesCacheBase+(stillFrameCacheCount-1)) 502 .arg(minindex).arg(maxindex)); 503 } 504 #endif 505 int i; 506 for (i = 0; i < stillFrameCacheCount; i++) 507 { 508 long long tmpframe = stillFramesCacheBase + i; 509 long long frameIndex = tmpframe - stillMainFrameNumber; 510 511 // frameIndex is the index matching stillFramesCache[i] to stillFrames[frameIndex] 512 // If frameIndex is within the stillFrames range, then use this frame 513 // otherwise delete it 514 515 if (frameIndex >= stillFrames.minIndex() && frameIndex <= stillFrames.maxIndex()) 516 { 517 // move cache data into normal arrays. 518 if (stillFrames[frameIndex]) 519 { 520 VERBOSE(VB_GENERAL, QString("Frame %1 index %2 already exists") 521 .arg(tmpframe).arg(frameIndex)); 522 // Can't move it -- the destination exists 523 delete stillFramesCache[i]; 524 delete stillFramesBigCache[i]; 525 } 526 else 527 { 528 cutFrames[frameIndex] = cutFramesCache[i]; 529 stillFrames[frameIndex] = stillFramesCache[i]; 530 stillFramesBig[frameIndex] = stillFramesBigCache[i]; 531 } 532 } 533 else 534 { 535 delete stillFramesCache[i]; 536 delete stillFramesBigCache[i]; 537 } 538 cutFramesCache[i]=0; 539 stillFramesCache[i] = NULL; 540 stillFramesBigCache[i] = NULL; 541 } 542 stillFrameCacheCount = 0; 543 } 544 545 void GridEditImages::printStillFrameStats(QString caption) 546 { 547 int i; 548 // Debug info for frame cache 549 QString foundframes= caption + " Found Frames: "; 550 551 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 552 if (stillFrames[i]) 553 foundframes += QString("%1 ").arg(i); 554 555 VERBOSE(VB_GENERAL, foundframes); 556 } 557 558 void GridEditImages::refreshCutList(MythUICutPointImage* gridimagemain, 559 myArray<MythUICutPointImage*, MAX_SUB_VIDEOS> &gridimages) 560 { 561 int i; 562 for (i = stillFrames.minIndex(); i <= stillFrames.maxIndex(); i++) 563 { 564 if (stillFrames[i]) 565 { 566 cutFrames[i] = m_player->GetCutStatus(stillMainFrameNumber+i); 567 if (gridimages[i]) 568 gridimages[i]->setCutStatus(cutFrames[i]); 569 } 570 } 571 572 gridimagemain->setCutStatus(cutFrames[0]); 573 } 574 575 bool GridEditImages::refreshImages(MythUICutPointImage* gridimagemain, 576 myArray<MythUICutPointImage*, MAX_SUB_VIDEOS> &gridimages, 577 bool mainFrameOnly) 578 { 579 FUNCTIONLOGGER; 580 // VERBOSE(VB_GENERAL, "Start"); 581 bool alldone = true; 582 if (!stillFramesBig[0]) 583 VERBOSE(VB_GENERAL, QString("Null Big Main frame %1").arg(stillMainFrameNumber)); 584 gridimagemain->SetPixmap(stillFramesBig[0], 585 stillMainFrameNumber, 586 cutFrames[0]); 587 588 if (mainFrameOnly && gridimages[0]) 589 gridimages[0]->SetPixmap(stillFrames[0], 590 stillMainFrameNumber, 591 cutFrames[0]); 592 593 if (!mainFrameOnly) 594 { 595 int i; 596 for (i = -usedSubVideoCount; i <= usedSubVideoCount; i++) 597 { 598 if (stillFrames[i] == NULL) 599 alldone = false; 600 if (gridimages[i]) 601 gridimages[i]->SetPixmap(stillFrames[i], 602 (stillMainFrameNumber + i), 603 cutFrames[i]); 604 } 605 } 606 607 // VERBOSE(VB_GENERAL, "Finish"); 608 return alldone; 609 } 610 611 612 // Back up x frames 613 void GridEditImages::SeekLeft(long long seekamount, bool cutpointseek) 614 { 615 lastmovewasright = false; 616 stopFrameCaching(); 617 m_editor->displayCacheStatus(0); 618 619 if (cutpointseek) 620 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, false); 621 622 //VERBOSE(VB_GENERAL, QString("SeekLeft %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 623 624 if (cutpointseek) 625 SetPreCache(-1); 626 else 627 SetPreCache(-seekamount); 628 629 if (!shiftStillFramesLeft(seekamount)) 630 { 631 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 632 // .arg(seekamount)); 633 // Need to grab the main frame 634 635 getMainStillFrame(); 636 } 637 638 startFrameCaching(); 639 } 640 641 void GridEditImages::SeekRight(long long seekamount, bool cutpointseek) 642 { 643 lastmovewasright = true; 644 stopFrameCaching(); 645 m_editor->displayCacheStatus(0); 646 647 if (cutpointseek) 648 seekamount = m_player->CalcCutPointSeek(stillMainFrameNumber, true); 649 650 //VERBOSE(VB_GENERAL, QString("SeekRight %1, cutpoint = %2").arg(seekamount).arg(cutpointseek)); 651 652 if (cutpointseek) 653 SetPreCache(1); 654 else 655 SetPreCache(seekamount); 656 657 if (!shiftStillFramesRight(seekamount)) 658 { 659 //VERBOSE(VB_GENERAL, QString("shiftStillFramesLeft(%1) == false") 660 // .arg(seekamount)); 661 // Need to grab the main frame 662 663 getMainStillFrame(); 664 } 665 666 startFrameCaching(); 667 } 668 669 void GridEditImages::checkMaxFrameCount() 670 { 671 long long tfc = m_player->GetTotalFrameCount(); 672 if (tfc != maxFrameNumberNVP) 673 { 674 VERBOSE(VB_GENERAL, QString("Updating: tfc %1, mfn %2, mfnNVP %3") 675 .arg(tfc).arg(maxFrameNumber).arg(maxFrameNumberNVP)); 676 // Check to see if things changed 677 maxFrameNumber = tfc; 678 maxFrameNumberNVP = tfc; 679 } 680 } 681 682 FrameStats GridEditImages::GetMainFrameStats() 683 { 684 FrameStats result; 685 686 result.frameNumber = stillMainFrameNumber; 687 result.cutInd = cutFrames[0]; 688 result.maxFrameNumber = maxFrameNumber; 689 690 return result; 691 } 692 -
new file mythbuild/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 class MythUICutPointImage; 15 16 #define MAX_SUB_VIDEOS 25 17 18 // Simple class to allow array indexing from -MAX_SUB_VIDEOS to +MAX_SUB_VIDEOS 19 template<class T, int COUNT> class myArray 20 { 21 public: 22 myArray() { memset(_array, 0, sizeof(_array));}; 23 24 T& operator[](int i) { return _array[COUNT+i]; }; 25 int minIndex() const { return -COUNT; }; 26 int maxIndex() const { return COUNT; }; 27 28 private: 29 T _array[2*COUNT+1]; 30 }; 31 32 class FrameStats 33 { 34 public: 35 long long frameNumber; 36 int cutInd; 37 long long maxFrameNumber; 38 }; 39 40 class MPUBLIC GridEditImages : public QObject 41 { 42 Q_OBJECT 43 44 public: 45 GridEditImages(GridEditCutpoints *er, NuppelVideoPlayer *player); 46 ~GridEditImages(); 47 48 void refreshCutList(MythUICutPointImage* gridimagemain, 49 myArray<MythUICutPointImage*, MAX_SUB_VIDEOS> &gridimages); 50 51 // return true if anything changed 52 bool refreshImages(MythUICutPointImage* gridimagemain, 53 myArray<MythUICutPointImage*, MAX_SUB_VIDEOS> &gridimages, 54 bool mainFrameOnly); 55 56 void SeekLeft(long long seekamount, bool cutpointseek = false); 57 void SeekRight(long long seekamount, bool cutpointseek = false); 58 59 FrameStats GetMainFrameStats(); 60 long long GetCurrentFrameNumber() const { return stillMainFrameNumber; } 61 long long GetMaxFrameNumber() const { return maxFrameNumber; } 62 63 void SetVideoInfo(int vcount, QSize sizeMain, QSize sizeSmall); 64 65 protected slots: 66 void updateAllFrames(); 67 68 private: 69 // Private functions 70 void clearStillFrames(); 71 void printStillFrameStats(QString caption); 72 void checkMaxFrameCount(); 73 74 // 'newlevel' paramter for getStillFrames(): 75 // 0 = get on screen Frames only 76 // 1 = get preCache Frames only 77 // 2 = get any necessary frames 78 // 3 = done 79 bool getFrameIndexes(int newlevel); 80 81 bool getStillFrames(int maxcount = 1000); 82 void getMainStillFrame(); 83 bool getSpecificFrame(long long frameindex); 84 void getFrame(long long i, int &cutFrame, QPixmap* &stillFrame, QPixmap* &stillFrameBig); 85 void emptyCache(); 86 87 // return true if anything changed 88 bool shiftStillFramesLeft(long long offset); 89 bool shiftStillFramesRight(long long offset); 90 void startFrameCaching(); 91 void stopFrameCaching() { getImagesTimer->stop(); }; 92 93 QPixmap *makeScaledPixmap(const QImage& qim, QSize sz); 94 95 void SetPreCache(long long pccount); 96 97 // Private data 98 // These frames are in the cutlist 99 // 0 == not cut 100 // 1 == cut 101 // 2 == cutpoint (cut left) 102 // 3 == cutpoint (cut right) 103 myArray<int, MAX_SUB_VIDEOS> cutFrames; 104 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFrames; 105 myArray<QPixmap *, MAX_SUB_VIDEOS> stillFramesBig; 106 107 // pre-caching large seek amounts 108 // (i.e. while seeking +5 seconds, these are places to store the to-be-displayed data) 109 110 int cutFramesCache[MAX_SUB_VIDEOS]; 111 QPixmap *stillFramesCache[MAX_SUB_VIDEOS]; 112 QPixmap *stillFramesBigCache[MAX_SUB_VIDEOS]; 113 int stillFrameCacheCount; 114 long long stillFramesCacheBase; // Frame # for index[0] 115 116 QSize videoSizeMain; 117 QSize videoSizeSmall; 118 int usedSubVideoCount; 119 long long preCacheIndexLeft; 120 long long preCacheIndexRight; 121 long long frameIndexLeft; 122 long long frameIndexRight; 123 bool lastmovewasright; 124 bool getFutureFramesFirst; 125 int frameCacheLevel; 126 127 long long stillMainFrameNumber; // frame number for big still picture 128 long long currentFrameNumberNVP; // frame number the NVP should be on 129 long long maxFrameNumber; // max frame number override for NVP 130 long long maxFrameNumberNVP; // Original NVP number 131 132 GridEditCutpoints *m_editor; 133 NuppelVideoPlayer *m_player; 134 135 QTimer *getImagesTimer; 136 137 }; 138 139 #endif -
mythtv/libs/libmythtv/libmythtv.pro
old new using_frontend { 336 336 SOURCES += ttfont.cpp 337 337 HEADERS += DetectLetterbox.h 338 338 SOURCES += DetectLetterbox.cpp 339 HEADERS += grideditcutpoints.h grideditimages.h 340 SOURCES += grideditcutpoints.cpp grideditimages.cpp 339 341 340 342 using_mheg { 341 343 # DSMCC stuff -
mythtv/libs/libmythtv/tv_play.cpp
old new using namespace std; 28 28 #include "remoteencoder.h" 29 29 #include "remoteutil.h" 30 30 #include "tvremoteutil.h" 31 #include "grideditcutpoints.h" 31 32 #include "NuppelVideoPlayer.h" 32 33 #include "DetectLetterbox.h" 33 34 #include "programinfo.h" … … using namespace std; 72 73 #define LOC_WARN QString("TV Warning: ") 73 74 #define LOC_ERR QString("TV Error: ") 74 75 76 #ifndef FUNCTIONLOGGER 77 #define FUNCTIONLOGGER 78 #endif 79 75 80 #define GetPlayer(X,Y) GetPlayerHaveLock(X, Y, __FILE__ , __LINE__) 76 81 #define GetOSDLock(X) GetOSDL(X, __FILE__, __LINE__) 77 82 … … EMBEDRETURNVOIDEPG TV::RunProgramGuidePt 135 140 */ 136 141 EMBEDRETURNVOIDFINDER TV::RunProgramFinderPtr = NULL; 137 142 143 /** 144 * \brief function pointer for RunGridEditCutpoints in grideditcutpoints.cpp 145 */ 146 EMBEDRETURNVOIDGEC TV::RunGridEditCutpointsPtr = NULL; 138 147 139 148 /** 140 149 * \brief If any cards are configured, return the number. … … void TV::SetFuncPtr(const char *string, 451 460 RunProgramFinderPtr = (EMBEDRETURNVOIDFINDER)lptr; 452 461 else if (name == "scheduleeditor") 453 462 RunScheduleEditorPtr = (EMBEDRETURNVOIDSCHEDIT)lptr; 463 else if (name == "grideditcutpoints") 464 RunGridEditCutpointsPtr = (EMBEDRETURNVOIDGEC)lptr; 465 else 466 VERBOSE(VB_IMPORTANT, QString("Unknown Function specified: %1").arg(string)); 454 467 } 455 468 456 469 void TV::InitKeys(void) … … void TV::InitKeys(void) 726 739 "Jump back 10x the normal amount"), ",,<"); 727 740 REG_KEY("TV Editing", "BIGJUMPFWD", QT_TRANSLATE_NOOP("MythControls", 728 741 "Jump forward 10x the normal amount"), ">,."); 742 REG_KEY("TV Editing", "EDIT", "Exit out of Edit Mode", "E"); 743 REG_KEY("TV Editing", "SLOWMO", "Slow Motion Play", "Ctrl+P"); 744 REG_KEY("TV Editing", "PAUSE", "Pause", "P"); 729 745 730 746 /* Teletext keys */ 731 747 REG_KEY("Teletext Menu", "NEXTPAGE", QT_TRANSLATE_NOOP("MythControls", … … TV::TV(void) 871 887 pseudoChangeChanTimerId(0), speedChangeTimerId(0), 872 888 errorRecoveryTimerId(0), exitPlayerTimerId(0) 873 889 { 874 VERBOSE(VB_PLAYBACK, LOC + "ctor -- begin");890 //VERBOSE(VB_PLAYBACK, LOC + "ctor -- begin"); 875 891 ctorTime.start(); 876 892 877 893 setObjectName("TV"); … … TV::TV(void) 993 1009 player.push_back(new PlayerContext(kPlayerInUseID)); 994 1010 playerActive = 0; 995 1011 playerLock.unlock(); 996 VERBOSE(VB_PLAYBACK, LOC + "ctor -- end");1012 // VERBOSE(VB_PLAYBACK, LOC + "ctor -- end"); 997 1013 } 998 1014 999 1015 /** \fn TV::Init(bool) … … void TV::ProcessKeypress(PlayerContext * 3563 3579 if (editmode) 3564 3580 { 3565 3581 actx->LockDeleteNVP(__FILE__, __LINE__); 3582 if (actx->nvp && actx->nvp->GetHideEdits()) 3583 { 3584 actx->UnlockDeleteNVP(__FILE__, __LINE__); 3585 return; 3586 } 3566 3587 if (actx->nvp && !actx->nvp->DoKeypress(e)) 3567 3588 editmode = actx->nvp->GetEditMode(); 3568 3589 actx->UnlockDeleteNVP(__FILE__, __LINE__); … … bool TV::ToggleHandleAction(PlayerContex 4541 4562 if (islivetv) 4542 4563 StartChannelEditMode(ctx); 4543 4564 else if (!isDVD) 4565 //DoEditRecordingGrid(); 4544 4566 StartProgramEditMode(ctx); 4545 4567 } 4546 4568 else … … void TV::StopEmbedding(PlayerContext *ct 8022 8044 8023 8045 void TV::DrawUnusedRects(void) 8024 8046 { 8025 VERBOSE(VB_PLAYBACK, LOC + "DrawUnusedRects() -- begin");8047 // VERBOSE(VB_PLAYBACK, LOC + "DrawUnusedRects() -- begin"); 8026 8048 8027 8049 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 8028 8050 for (uint i = 0; mctx && (i < player.size()); i++) … … void TV::DrawUnusedRects(void) 8035 8057 } 8036 8058 ReturnPlayerLock(mctx); 8037 8059 8038 VERBOSE(VB_PLAYBACK, LOC + "DrawUnusedRects() -- end");8060 // VERBOSE(VB_PLAYBACK, LOC + "DrawUnusedRects() -- end"); 8039 8061 } 8040 8062 8041 8063 vector<bool> TV::DoSetPauseState(PlayerContext *lctx, const vector<bool> &pause) … … vector<bool> TV::DoSetPauseState(PlayerC 8060 8082 return was_paused; 8061 8083 } 8062 8084 8085 void TV::DoEditRecordingGrid() 8086 { 8087 FUNCTIONLOGGER; 8088 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 8089 8090 actx->LockPlayingInfo(__FILE__, __LINE__); 8091 if (!actx->playingInfo) 8092 { 8093 VERBOSE(VB_IMPORTANT, 8094 LOC_ERR + "no active ctx playingInfo."); 8095 actx->UnlockPlayingInfo(__FILE__, __LINE__); 8096 ReturnPlayerLock(actx); 8097 return; 8098 } 8099 actx->UnlockPlayingInfo(__FILE__, __LINE__); 8100 8101 // Resize window to the MythTV GUI size 8102 PlayerContext *mctx = GetPlayer(actx,0); 8103 mctx->LockDeleteNVP(__FILE__, __LINE__); 8104 if (mctx->nvp && mctx->nvp->getVideoOutput()) 8105 mctx->nvp->getVideoOutput()->ResizeForGui(); 8106 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 8107 ReturnPlayerLock(actx); 8108 8109 MythMainWindow *mwnd = gContext->GetMainWindow(); 8110 if (!db_use_gui_size_for_tv || !db_use_fixed_size) 8111 { 8112 mwnd->setGeometry(saved_gui_bounds.left(), saved_gui_bounds.top(), 8113 saved_gui_bounds.width(), saved_gui_bounds.height()); 8114 mwnd->setFixedSize(saved_gui_bounds.size()); 8115 } 8116 8117 // Actually show the pop-up UI 8118 8119 RunGridEditCutpointsPtr(this); 8120 ignoreKeyPresses = true; 8121 8122 //we are embedding in a mythui window so show the gui paint window again 8123 GetMythMainWindow()->SetDrawEnabled(true); 8124 GetMythMainWindow()->GetPaintWindow()->show(); 8125 } 8126 8063 8127 void TV::DoEditSchedule(int editType) 8064 8128 { 8065 8129 if ((editType == kScheduleProgramGuide && !RunProgramGuidePtr) || … … void TV::EditSchedule(const PlayerContex 8191 8255 qApp->postEvent(gContext->GetMainWindow(), me); 8192 8256 } 8193 8257 8258 void TV::ShowEditRecordingGrid() 8259 { 8260 FUNCTIONLOGGER; 8261 // post the request to the main UI thread 8262 // it will be caught in eventFilter and processed as CustomEvent 8263 // this will create the program guide window (widget) 8264 // on the main thread and avoid a deadlock on Win32 8265 8266 VERBOSE(VB_GENERAL, "Starting Grid Edit"); 8267 QString message = QString("START_EDIT"); 8268 MythEvent* me = new MythEvent(message); 8269 qApp->postEvent(gContext->GetMainWindow(), me); 8270 } 8271 8194 8272 void TV::ChangeVolume(PlayerContext *ctx, bool up) 8195 8273 { 8196 8274 ctx->LockDeleteNVP(__FILE__, __LINE__); … … void TV::customEvent(QEvent *e) 8883 8961 } 8884 8962 8885 8963 if (message.left(11) == "EPG_EXITING" || 8964 message.left(16) == "GRIDEDIT_EXITING" || 8886 8965 message.left(18) == "PROGFINDER_EXITING" || 8887 8966 message.left(21) == "VIEWSCHEDULED_EXITING" || 8888 8967 message.left(19) == "PLAYBACKBOX_EXITING" || … … void TV::customEvent(QEvent *e) 8939 9018 8940 9019 } 8941 9020 9021 if (message.left(10) == "START_EDIT") 9022 { 9023 DoEditRecordingGrid(); 9024 } 9025 8942 9026 if (message.left(14) == "COMMFLAG_START") 8943 9027 { 8944 9028 QString evchanid = QString::null; … … void TV::TreeMenuSelected(OSDListTreeIte 10172 10256 } 10173 10257 else if (action == "EDIT") 10174 10258 StartProgramEditMode(actx); 10259 //DoEditRecordingGrid(); 10175 10260 else if (action == "TOGGLEAUTOEXPIRE") 10176 10261 ToggleAutoExpire(actx); 10177 10262 else if (action.left(14) == "TOGGLECOMMSKIP") -
mythtv/libs/libmythtv/tv_play.h
old new typedef void (*EMBEDRETURNVOID) (void *, 63 63 typedef void (*EMBEDRETURNVOIDEPG) (uint, const QString &, TV *, bool, bool, int); 64 64 typedef void (*EMBEDRETURNVOIDFINDER) (TV *, bool, bool); 65 65 typedef void (*EMBEDRETURNVOIDSCHEDIT) (const ProgramInfo *, void *); 66 typedef void (*EMBEDRETURNVOIDGEC) (TV *); 66 67 67 68 // Locking order 68 69 // … … class MPUBLIC TV : public QThread 166 167 friend class PlaybackBox; 167 168 friend class GuideGrid; 168 169 friend class TvPlayWindow; 170 friend class GridEditCutpoints; 169 171 170 172 Q_OBJECT 171 173 public: … … class MPUBLIC TV : public QThread 213 215 void setInPlayList(bool setting) { inPlaylist = setting; } 214 216 void setUnderNetworkControl(bool setting) { underNetworkControl = setting; } 215 217 218 void ShowEditRecordingGrid(); 216 219 void ShowNoRecorderDialog(const PlayerContext*, 217 220 NoRecorderMsg msgType = kNoRecorders); 218 221 void FinishRecording(int player_idx); ///< Finishes player's recording … … class MPUBLIC TV : public QThread 298 301 void TreeMenuSelected(OSDListTreeItemSelectedEvent *e); 299 302 300 303 void DoEditSchedule(int editType = kScheduleProgramGuide); 304 void DoEditRecordingGrid(); 301 305 302 306 virtual void run(void); 303 307 void TVEventThreadChecks(void); … … class MPUBLIC TV : public QThread 312 316 static EMBEDRETURNVOIDEPG RunProgramGuidePtr; 313 317 static EMBEDRETURNVOIDFINDER RunProgramFinderPtr; 314 318 static EMBEDRETURNVOIDSCHEDIT RunScheduleEditorPtr; 319 static EMBEDRETURNVOIDGEC RunGridEditCutpointsPtr; 315 320 316 321 private: 317 322 void SetActive(PlayerContext *lctx, int index, bool osd_msg); -
mythtv/themes/MythCenter-wide/recordings-ui.xml
old new 1085 1085 </buttonlist> 1086 1086 </window> 1087 1087 1088 <window name="grideditcutpoints"> 1089 <font name="white_medium" face="DejaVu Sans"> 1090 <color>#FFFFFF</color> 1091 <size>20</size> 1092 </font> 1093 1094 <font name="yellow_medium" face="DejaVu Sans"> 1095 <color>#FFFF00</color> 1096 <size>20</size> 1097 </font> 1098 1099 <area>0,0,1280,720</area> 1100 1101 <textarea name="timecap" align="right"> 1102 <area>0,350,120,40</area> 1103 <font>white_medium</font> 1104 <value>Time:</value> 1105 </textarea> 1106 1107 <textarea name="time" align="left"> 1108 <area>125,350,195,40</area> 1109 <font>white_medium</font> 1110 </textarea> 1111 1112 <textarea name="framenumcap" align="right"> 1113 <area>0,400,120,40</area> 1114 <font>white_medium</font> 1115 <value>Frame:</value> 1116 </textarea> 1117 1118 <textarea name="framenum" align="left" > 1119 <area>125,400,195,40</area> 1120 <font>white_medium</font> 1121 </textarea> 1122 1123 <textarea name="cutind" align="left" > 1124 <area>120,450,195,40</area> 1125 <font>white_medium</font> 1126 </textarea> 1127 1128 <textarea name="updatingind" align="center" > 1129 <area>20,550,210,40</area> 1130 <font>yellow_medium</font> 1131 <value>Updating</value> 1132 </textarea> 1133 1134 <textarea name="jumpstylecap" align="right" > 1135 <area>0,500,120,40</area> 1136 <font>white_medium</font> 1137 <value>Skip:</value> 1138 </textarea> 1139 1140 <textarea name="jumpstyle" align="left" > 1141 <area>125,500,195,40</area> 1142 <font>white_medium</font> 1143 </textarea> 1144 1145 <cutpointbar name="positionbar"> 1146 <area>338,554,908,48</area> 1147 <fillcolor>#202020</fillcolor> 1148 <cutcolor>#7f0000</cutcolor> 1149 <incutcolor>#7f7f00</incutcolor> 1150 <cutpointcolor>#FFFF00</cutpointcolor> 1151 <positioncolor>#FFFFFF</positioncolor> 1152 </cutpointbar> 1153 1154 1155 <cutpointimage name="mainvideo"> 1156 <area>328,24,928,522</area> 1157 <outlinecolor>#202020</outlinecolor> 1158 <cutcolor>#7f0000</cutcolor> 1159 <cutpointcolor>#afaf00</cutpointcolor> 1160 </cutpointimage> 1161 1162 <cutpointimage name="videom3" from="mainvideo"> 1163 <area>6,614,176,99</area> 1164 </cutpointimage> 1165 1166 <cutpointimage name="videom2" from="mainvideo"> 1167 <area>188,614,176,99</area> 1168 </cutpointimage> 1169 1170 <cutpointimage name="videom1" from="mainvideo"> 1171 <area>370,614,176,99</area> 1172 </cutpointimage> 1173 1174 <cutpointimage name="video0" from="mainvideo"> 1175 <area>552,614,176,99</area> 1176 <highlightcolor>#ffffff</highlightcolor> 1177 </cutpointimage> 1178 1179 <cutpointimage name="videop1" from="mainvideo"> 1180 <area>734,614,176,99</area> 1181 </cutpointimage> 1182 1183 <cutpointimage name="videop2" from="mainvideo"> 1184 <area>916,614,176,99</area> 1185 </cutpointimage> 1186 1187 <cutpointimage name="videop3" from="mainvideo"> 1188 <area>1098,614,176,99</area> 1189 </cutpointimage> 1190 1191 </window> 1192 1088 1193 </mythuitheme> -
mythtv/programs/mythfrontend/main.cpp
old new using namespace std; 69 69 #include "mythdb.h" 70 70 #include "backendconnectionmanager.h" 71 71 72 #include "grideditcutpoints.h" 73 72 74 static ExitPrompter *exitPopup = NULL; 73 75 static MythThemedMenu *menu; 74 76 static MythThemeBase *themeBase = NULL; … … void InitJumpPoints(void) 965 967 TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide); 966 968 TV::SetFuncPtr("programfinder", (void *)RunProgramFinder); 967 969 TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor); 970 TV::SetFuncPtr("grideditcutpoints", (void *)GridEditCutpoints::RunGridEditCutpoints); 968 971 } 969 972 970 973 -
mythtv/programs/mythfrontend/guidegrid.cpp
old new void GuideGrid::RunProgramGuide(uint cha 208 208 mainStack->AddScreen(gg, (player == NULL)); 209 209 else 210 210 delete gg; 211 212 QString depth = mainStack->GetLocation(true); 213 214 VERBOSE(VB_GENERAL, QString("Screens: %1").arg(depth)); 211 215 } 212 216 213 217 GuideGrid::GuideGrid(MythScreenStack *parent, -
mythtv/libs/libmythui/mythscreenstack.cpp
old new 4 4 #include "mythpainter.h" 5 5 #include "mythevent.h" 6 6 7 #include "mythverbose.h" 8 7 9 #include <cassert> 8 10 9 11 #include <QCoreApplication> … … void MythScreenStack::AddScreen(MythScre 75 77 screen->aboutToShow(); 76 78 77 79 m_topScreen = screen; 80 81 // reinterpret_cast<MythMainWindow *>(parent())->ShowAllStacksBut(objectName()); 82 // QString loc = GetLocation(true); 83 // VERBOSE(VB_GENERAL, QString("Location ('%1') = %2").arg(objectName()).arg(loc)); 78 84 } 79 85 80 86 void MythScreenStack::PopScreen(bool allowFade, … … void MythScreenStack::PopScreen(MythScre 89 95 if (!screen || screen->IsDeleting()) 90 96 return; 91 97 98 QString popname = screen->objectName(); 99 92 100 screen->aboutToHide(); 93 101 94 102 if (m_Children.isEmpty()) … … void MythScreenStack::PopScreen(MythScre 160 168 if (mainscreen) 161 169 mainscreen->SetRedraw(); 162 170 } 171 172 // QString loc = GetLocation(true); 173 // VERBOSE(VB_GENERAL, QString("Location ('%1') = %2 popped %3").arg(objectName()).arg(loc).arg(popname)); 174 // reinterpret_cast<MythMainWindow *>(parent())->ShowAllStacksBut(objectName()); 163 175 } 164 176 165 177 MythScreenType *MythScreenStack::GetTopScreen(void) const -
mythtv/libs/libmythdb/mythobservable.cpp
old new 3 3 #include <QMutex> 4 4 5 5 #include "mythobservable.h" 6 #include "mythverbose.h" 6 7 7 8 /** \class MythObservable 8 9 * \brief Superclass for making an object have a set of listeners … … void MythObservable::addListener(QObject 43 44 { 44 45 if (listener) 45 46 { 47 VERBOSE(VB_GENERAL, QString("Adding '%1'").arg(listener->objectName())); 46 48 QMutexLocker locker(m_lock); 47 49 m_listeners.insert(listener); 48 50 } 51 // ShowListeners(); 49 52 } 50 53 51 54 … … void MythObservable::removeListener(QObj 60 63 { 61 64 if (listener) 62 65 { 66 VERBOSE(VB_GENERAL, QString("Removing '%1'").arg(listener->objectName())); 63 67 QMutexLocker locker(m_lock); 64 68 m_listeners.remove(listener); 65 69 QCoreApplication::removePostedEvents(listener); 66 70 } 71 // ShowListeners(); 72 } 73 74 void MythObservable::ShowListeners() 75 { 76 QString output=""; 77 { 78 QMutexLocker locker(m_lock); 79 80 QSet<QObject*>::const_iterator it = m_listeners.begin(); 81 for (; it != m_listeners.end() ; ++it) 82 { 83 QString oname = (*it)->objectName(); 84 if (oname != "") 85 output = output + oname + ", "; 86 else 87 output = output + "<none>, "; 88 } 89 } 90 VERBOSE(VB_GENERAL, QString("Listeners = '%1'").arg(output)); 67 91 } 68 92 69 93 /** \brief Dispatch an event to all listeners … … void MythObservable::removeListener(QObj 76 100 */ 77 101 void MythObservable::dispatch(const MythEvent &event) 78 102 { 103 // VERBOSE(VB_GENERAL, QString("Dispatching '%1'").arg(event.Message())); 79 104 QMutexLocker locker(m_lock); 80 105 81 106 QSet<QObject*>::const_iterator it = m_listeners.begin(); … … void MythObservable::dispatch(const Myth 92 117 */ 93 118 void MythObservable::dispatchNow(const MythEvent &event) 94 119 { 120 // VERBOSE(VB_GENERAL, QString("DispatchingNow '%1'").arg(event.Message())); 95 121 QMutexLocker locker(m_lock); 96 122 97 123 QSet<QObject*>::const_iterator it = m_listeners.begin(); -
mythtv/libs/libmythdb/mythobservable.h
old new class MPUBLIC MythObservable 20 20 void dispatch(const MythEvent &event); 21 21 void dispatchNow(const MythEvent &event) MDEPRECATED; 22 22 23 void ShowListeners(); 24 23 25 private: 24 26 QMutex *m_lock; 25 27 QSet<QObject*> m_listeners; -
mythtv/libs/libmythui/mythmainwindow.cpp
old new MythScreenStack *MythMainWindow::GetStac 581 581 return NULL; 582 582 } 583 583 584 void MythMainWindow::ShowAllStacksBut(QString name) 585 { 586 QVector<MythScreenStack *>::Iterator it; 587 for (it = d->stackList.begin(); it != d->stackList.end(); ++it) 588 { 589 if ((*it)->objectName() != name) 590 { 591 QString loc = (*it)->GetLocation(true); 592 VERBOSE(VB_GENERAL, QString("Location ('%1' != '%2') = %3").arg((*it)->objectName()).arg(name).arg(loc)); 593 } 594 } 595 } 596 584 597 void MythMainWindow::RegisterSystemEventHandler(QObject *eventHandler) 585 598 { 586 599 d->sysEventHandler = eventHandler; -
mythtv/libs/libmythui/mythmainwindow.h
old new class MPUBLIC MythMainWindow : public QW 110 110 void SetDrawEnabled(bool enable); 111 111 void SetEffectsEnabled(bool enable); 112 112 113 void ShowAllStacksBut(QString name); 114 113 115 public slots: 114 116 void mouseTimeout(); 115 117 -
mythtv/libs/libmythui/mythuishape.cpp
old new using namespace std; 18 18 #include "mythimage.h" 19 19 #include "mythmainwindow.h" 20 20 21 #ifndef FUNCTIONLOGGER 22 #define FUNCTIONLOGGER 23 #endif 24 21 25 MythUIShape::MythUIShape(MythUIType *parent, const QString &name) 22 26 : MythUIType(parent, name) 23 27 { … … MythUIShape::MythUIShape(MythUIType *par 26 30 m_fillBrush = QBrush(Qt::NoBrush); 27 31 m_linePen = QPen(Qt::NoPen); 28 32 m_cornerRadius = 10; 33 m_pm = NULL; 29 34 } 30 35 31 36 MythUIShape::~MythUIShape() … … void MythUIShape::Reset() 51 56 void MythUIShape::DrawSelf(MythPainter *p, int xoffset, int yoffset, 52 57 int alphaMod, QRect clipRect) 53 58 { 59 //FUNCTIONLOGGER; 60 // if (m_image) 61 // VERBOSE(VB_GENERAL, QString("Has Image 1 (null? %1), has pixmap %2").arg(m_image->isNull()).arg(m_pm != NULL)); 62 // else 63 // VERBOSE(VB_GENERAL, QString("Has Image 0, has pixmap %1").arg(m_pm != NULL)); 64 54 65 QRect area = GetArea(); 55 66 area.translate(xoffset, yoffset); 56 67 … … void MythUIShape::DrawSelf(MythPainter * 62 73 DrawRoundRect(area, m_cornerRadius, m_fillBrush, m_linePen); 63 74 } 64 75 65 if (m_image) 76 if (m_image) { 77 // VERBOSE(VB_GENERAL, QString("Drawing (%1, %2, xx, %3)").arg(area.x()).arg(area.y()).arg(alphaMod)); 66 78 p->DrawImage(area.x(), area.y(), m_image, alphaMod); 79 } 80 } 81 82 void MythUIShape::SetPixmap(QPixmap * pm) 83 { 84 //FUNCTIONLOGGER; 85 m_pm = pm; 86 87 if (m_image) 88 { 89 m_image->DownRef(); 90 m_image = NULL; 91 } 92 93 m_image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage(); 94 m_image->UpRef(); 95 if (m_pm) 96 m_image->Assign(*m_pm); 97 98 SetRedraw(); 67 99 } 68 100 69 101 void MythUIShape::DrawRect(const QRect &area,const QBrush &fillBrush, 70 102 const QPen &linePen) 71 103 { 104 //FUNCTIONLOGGER; 72 105 if (m_image) 73 106 { 74 107 m_image->DownRef(); … … void MythUIShape::DrawRect(const QRect & 93 126 94 127 m_image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage(); 95 128 m_image->UpRef(); 96 m_image->Assign(image); 129 if (m_pm) { 130 // VERBOSE(VB_GENERAL, "m_pm != NULL"); 131 m_image->Assign(*m_pm); 132 } else { 133 // VERBOSE(VB_GENERAL, "m_pm == NULL"); 134 m_image->Assign(image); 135 } 97 136 } 98 137 99 138 void MythUIShape::DrawRoundRect(const QRect &area, int radius, 100 139 const QBrush &fillBrush, const QPen &linePen) 101 140 { 141 //FUNCTIONLOGGER; 102 142 if (m_image) 103 143 { 104 144 m_image->DownRef(); … … void MythUIShape::DrawRoundRect(const QR 129 169 130 170 m_image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage(); 131 171 m_image->UpRef(); 132 m_image->Assign(image); 172 173 if (m_pm) { 174 // VERBOSE(VB_GENERAL, "m_pm != NULL"); 175 m_image->Assign(*m_pm); 176 } else { 177 // VERBOSE(VB_GENERAL, "m_pm == NULL"); 178 m_image->Assign(image); 179 } 133 180 } 134 181 135 182 bool MythUIShape::ParseElement( -
mythtv/libs/libmythui/mythuishape.h
old new class MPUBLIC MythUIShape : public MythU 20 20 21 21 void Reset(void); 22 22 23 void SetPixmap(QPixmap * pm); 24 23 25 protected: 24 26 virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, 25 27 int alphaMod, QRect clipRect); … … class MPUBLIC MythUIShape : public MythU 41 43 QBrush m_fillBrush; 42 44 QPen m_linePen; 43 45 int m_cornerRadius; 46 47 QPixmap *m_pm; 44 48 }; 45 49 46 50 #endif -
mythtv/libs/libmythui/libmythui.pro
old new HEADERS += themeinfo.h mythxdisplay.h Di 28 28 HEADERS += mythgenerictree.h mythuibuttontree.h mythuiutils.h 29 29 HEADERS += mythvirtualkeyboard.h mythuishape.h mythuiguidegrid.h 30 30 HEADERS += mythrender_base.h mythfontmanager.h 31 HEADERS += mythuicutpointbar.h mythuicutpointimage.h 31 32 32 33 SOURCES = mythmainwindow.cpp mythpainter.cpp mythimage.cpp mythrect.cpp 33 34 SOURCES += myththemebase.cpp … … SOURCES += themeinfo.cpp mythxdisplay.cp 44 45 SOURCES += mythgenerictree.cpp mythuibuttontree.cpp mythuiutils.cpp 45 46 SOURCES += mythvirtualkeyboard.cpp mythuishape.cpp mythuiguidegrid.cpp 46 47 SOURCES += mythfontmanager.cpp 48 SOURCES += mythuicutpointbar.cpp mythuicutpointimage.cpp 47 49 48 50 inc.path = $${PREFIX}/include/mythtv/libmythui/ 49 51 … … inc.files += mythuispinbox.h mythuicheck 58 60 inc.files += mythuiprogressbar.h mythuiwebbrowser.h mythuiutils.h 59 61 inc.files += mythsystem.h x11colors.h mythgenerictree.h mythuibuttontree.h 60 62 inc.files += mythvirtualkeyboard.h mythuishape.h mythuiguidegrid.h 63 inc.files += mythuicutpointbar.h mythuicutpointimage.h 61 64 62 65 INSTALLS += inc 63 66 -
new file mythbuild/mythtv/libs/libmythui/mythuicutpointbar.cpp
- + 1 2 // Own Header 3 #include "mythuicutpointbar.h" 4 5 // QT 6 #include <QCoreApplication> 7 #include <QDomDocument> 8 9 // MythDB 10 #include "mythverbose.h" 11 12 #ifndef FUNCTIONLOGGER 13 #define FUNCTIONLOGGER 14 #endif 15 16 // MythUI 17 18 19 MythUICutPointBar::MythUICutPointBar(MythUIType *parent, const QString &name) 20 : MythUIType(parent, name), 21 m_layout(LayoutHorizontal), m_effect(EffectReveal), 22 m_total(0), m_start(0), 23 m_current(0) 24 { 25 m_drawMap = NULL; 26 m_position=0; 27 } 28 29 void MythUICutPointBar::InitWidth() 30 { 31 if (m_drawMap) 32 delete [] m_drawMap; 33 34 m_drawWidth = GetArea().width(); 35 m_drawMap = new unsigned char[m_drawWidth]; 36 for (int i = 0; i < m_drawWidth; i++) 37 m_drawMap[i] = 0; 38 } 39 40 void MythUICutPointBar::Reset() 41 { 42 m_total = m_start = m_current = 0; 43 CalculatePosition(); 44 MythUIType::Reset(); 45 } 46 47 void MythUICutPointBar::SetRange( 48 long long fstart, long long fend, long long fcount) 49 { 50 if (fcount <= 0) 51 { 52 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 53 .arg(fcount)); 54 return; 55 } 56 if (fstart < 0) 57 { 58 VERBOSE(VB_IMPORTANT, QString("Invalid starting frame: %1") 59 .arg(fstart)); 60 return; 61 } 62 if (fend < 0) 63 { 64 VERBOSE(VB_IMPORTANT, QString("Invalid ending frame: %1") 65 .arg(fend)); 66 return; 67 } 68 69 if (fstart > fcount) fstart = fcount; 70 if (fend > fcount) fend = fcount; 71 72 int start = (int)((1.0 * fstart * m_drawWidth) / fcount); 73 int end = (int)((1.0 * fend * m_drawWidth) / fcount); 74 75 if (start < 0) 76 start = 0; 77 if (start >= m_drawWidth) 78 start = m_drawWidth - 1; 79 if (end < 0) 80 end = 0; 81 if (end >= m_drawWidth) 82 end = m_drawWidth - 1; 83 84 if (end < start) 85 { 86 int tmp = start; 87 start = end; 88 end = tmp; 89 } 90 91 for (int i = start; i < end; i++) 92 if (m_drawMap[i] < 1) 93 m_drawMap[i] = 1; 94 95 // Mark endpoints 96 97 m_drawMap[start] = 2; 98 m_drawMap[end] = 2; 99 100 VERBOSE(VB_GENERAL, QString("Range = %1 - %2 (%3 - %4)") 101 .arg(start).arg(end) 102 .arg(fstart).arg(fend)); 103 SetRedraw(); 104 } 105 106 void MythUICutPointBar::SetCurrentPosition( 107 long long fposition, long long fcount) 108 { 109 if (fcount <= 0) 110 { 111 VERBOSE(VB_IMPORTANT, QString("Invalid frame count: %1") 112 .arg(fcount)); 113 return; 114 } 115 116 if (fposition < 0) 117 { 118 VERBOSE(VB_IMPORTANT, QString("Invalid position frame: %1") 119 .arg(fposition)); 120 return; 121 } 122 123 if (fposition > fcount) fposition = fcount; 124 125 int new_position = (int)(1.0 * fposition * m_drawWidth) / fcount; 126 127 if (new_position < 0) 128 new_position = 0; 129 if (new_position >= m_drawWidth) 130 new_position = m_drawWidth - 1; 131 132 if (new_position != m_position) 133 { 134 m_position = new_position; 135 SetRedraw(); 136 } 137 } 138 139 140 141 bool MythUICutPointBar::ParseElement( 142 const QString &filename, QDomElement &element, bool showWarnings) 143 { 144 VERBOSE(VB_GENERAL, QString("Got %1").arg(element.tagName())); 145 146 if (element.tagName() == "fillcolor") 147 { 148 QColor color = getFirstText(element); 149 setFillColor(color); 150 } 151 else if (element.tagName() == "cutcolor") 152 { 153 QColor color = getFirstText(element); 154 setCutColor(color); 155 } 156 else if (element.tagName() == "incutcolor") 157 { 158 QColor color = getFirstText(element); 159 setInCutColor(color); 160 } 161 else if (element.tagName() == "incutcolor") 162 { 163 QColor color = getFirstText(element); 164 setInCutColor(color); 165 } 166 else if (element.tagName() == "cutpointcolor") 167 { 168 QColor color = getFirstText(element); 169 setCutPointColor(color); 170 } 171 else if (element.tagName() == "positioncolor") 172 { 173 QColor color = getFirstText(element); 174 setPositionColor(color); 175 } 176 else 177 { 178 return MythUIType::ParseElement(filename, element, showWarnings); 179 } 180 181 return true; 182 } 183 184 void MythUICutPointBar::SetStart(int value) 185 { 186 m_start = value; 187 CalculatePosition(); 188 } 189 190 void MythUICutPointBar::SetUsed(int value) 191 { 192 if (value < m_start) 193 value = m_start; 194 195 if (value > m_total) 196 value = m_total; 197 198 m_current = value; 199 CalculatePosition(); 200 } 201 202 void MythUICutPointBar::SetTotal(int value) 203 { 204 m_total = value; 205 CalculatePosition(); 206 } 207 208 void MythUICutPointBar::CalculatePosition(void) 209 { 210 MythUIImage *progressImage = dynamic_cast<MythUIImage *> 211 (GetChild("progressimage")); 212 213 if (!progressImage) 214 { 215 VERBOSE(VB_IMPORTANT, "Progress image doesn't exist"); 216 return; 217 } 218 219 progressImage->SetVisible(false); 220 221 int total = m_total-m_start; 222 int current = m_current-m_start; 223 float percentage = 0.0; 224 225 if (total <= 0 || current <= 0 || current > total) 226 return; 227 228 percentage = (float)current / (float)total; 229 progressImage->SetVisible(true); 230 231 QRect fillArea = progressImage->GetArea(); 232 233 int height = fillArea.height(); 234 int width = fillArea.width(); 235 int x = fillArea.x(); 236 int y = fillArea.y(); 237 238 switch (m_effect) 239 { 240 case EffectReveal : 241 if (m_layout == LayoutHorizontal) 242 { 243 width = (int)((float)fillArea.width() * percentage); 244 } 245 else 246 { 247 height = (int)((float)fillArea.height() * percentage); 248 } 249 break; 250 case EffectSlide : 251 if (m_layout == LayoutHorizontal) 252 { 253 int newwidth = (int)((float)fillArea.width() * percentage); 254 x = width - newwidth; 255 width = newwidth; 256 } 257 else 258 { 259 int newheight = (int)((float)fillArea.height() * percentage); 260 y = height - newheight; 261 height = newheight; 262 } 263 break; 264 case EffectAnimate : 265 // Not implemented yet 266 break; 267 } 268 269 if (width <= 0) 270 width = 1; 271 272 if (height <= 0) 273 height = 1; 274 275 // progressImage->SetCropRect(x,y,width,height); 276 SetRedraw(); 277 } 278 279 void MythUICutPointBar::CopyFrom(MythUIType *base) 280 { 281 MythUICutPointBar *progressbar = dynamic_cast<MythUICutPointBar *>(base); 282 if (!progressbar) 283 return; 284 285 m_layout = progressbar->m_layout; 286 m_effect = progressbar->m_effect; 287 288 m_total = progressbar->m_total; 289 m_start = progressbar->m_start; 290 m_current = progressbar->m_current; 291 292 MythUIType::CopyFrom(base); 293 } 294 295 void MythUICutPointBar::CreateCopy(MythUIType *parent) 296 { 297 MythUICutPointBar *progressbar = new MythUICutPointBar(parent, objectName()); 298 progressbar->CopyFrom(this); 299 } 300 301 void MythUICutPointBar::DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, 302 QRect clipRegion) 303 { 304 FUNCTIONLOGGER; 305 QRect fillArea = GetArea(); 306 307 int height = fillArea.height(); 308 int width = fillArea.width(); 309 int x = fillArea.x(); 310 int y = fillArea.y(); 311 312 VERBOSE(VB_GENERAL, QString(" area = (%1, %2, %3, %4)") 313 .arg(x).arg(y).arg(width).arg(height)); 314 315 p->DrawRect(fillArea, 316 true, colorSet[0], 317 false, 0, colorSet[0]); 318 319 if (m_drawMap) 320 { 321 int i = 0; 322 323 do { 324 int start = 0; 325 int end = 0; 326 327 while (i < m_drawWidth && m_drawMap[i] == 0) i++; 328 if (i == m_drawWidth) break; 329 start = i; 330 331 i++; 332 333 while (i < m_drawWidth && m_drawMap[i] == 1) i++; 334 end = i; 335 if (end == m_drawWidth) end--; 336 337 // If the next map value is not a normal internal cutpoint 338 // increment i so we handle it properly 339 if (end+1 < m_drawWidth && m_drawMap[end+1] != 1) 340 i++; 341 342 // start == starting point 343 // end == endingpoint 344 { 345 QRect r = fillArea; 346 r.setLeft(r.left() + start); 347 r.setWidth(end - start); 348 349 // VERBOSE(VB_GENERAL, QString("Cut from (%1, %2) - (%3, %4)") 350 // .arg(r.left()).arg(r.top()) 351 // .arg(r.right()).arg(r.bottom())); 352 353 // VERBOSE(VB_GENERAL, QString("start = %1, m_position = %2, end = %3") 354 // .arg(start) 355 // .arg(m_position) 356 // .arg(end)); 357 358 if (start <= m_position && m_position <= end) 359 { 360 p->DrawRect(r, 361 true, colorSet[4], 362 true, 2, colorSet[4]); 363 } 364 else 365 { 366 p->DrawRect(r, 367 true, colorSet[1], 368 true, 2, colorSet[4]); 369 } 370 371 if (m_drawMap[start] == 2) 372 { 373 QRect markArea(r.topLeft(), r.bottomLeft()); 374 p->DrawRect(markArea, 375 true, colorSet[2], 376 true, 2, colorSet[2]); 377 } 378 if (m_drawMap[end] == 2) 379 { 380 QRect markArea(r.topRight(), r.bottomRight()); 381 p->DrawRect(markArea, 382 true, colorSet[2], 383 true, 2, colorSet[2]); 384 } 385 } 386 } while (i < m_drawWidth); 387 } 388 // Draw Current Position Mark 389 390 QPoint ptop(fillArea.left() + m_position, fillArea.top()); 391 QPoint pbot(fillArea.left() + m_position, fillArea.bottom()); 392 393 QRect markArea(ptop, pbot); 394 p->DrawRect(markArea, 395 true, colorSet[3], 396 true, 2, colorSet[3]); 397 } 398 399 void MythUICutPointBar::ClearAll() 400 { 401 for (int i = 0; i < m_drawWidth; i++) 402 m_drawMap[i] = 0; 403 SetRedraw(); 404 } -
new file mythbuild/mythtv/libs/libmythui/mythuicutpointbar.h
- + 1 #ifndef MYTHUI_CUTPOINTBAR_H_ 2 #define MYTHUI_CUTPOINTBAR_H_ 3 4 #include "mythuitype.h" 5 #include "mythuiimage.h" 6 7 class MythFontProperties; 8 9 /** \class MythUIProgressBar 10 * 11 * \brief Progress bar widget. 12 * 13 */ 14 class MPUBLIC MythUICutPointBar : public MythUIType 15 { 16 public: 17 MythUICutPointBar(MythUIType *parent, const QString &name); 18 ~MythUICutPointBar() { } 19 20 void Reset(void); 21 22 enum LayoutType { LayoutVertical, LayoutHorizontal }; 23 enum EffectType { EffectReveal, EffectSlide, EffectAnimate }; 24 25 void SetStart(int); 26 void SetUsed(int); 27 void SetTotal(int); 28 29 void setFillColor(QColor c) { colorSet[0] = c; }; 30 void setCutColor(QColor c) { colorSet[1] = c; }; 31 void setCutPointColor(QColor c) { colorSet[2] = c; }; 32 void setPositionColor(QColor c) { colorSet[3] = c; }; 33 void setInCutColor(QColor c) { colorSet[4] = c; }; 34 35 void InitWidth(); 36 void ClearAll(); 37 void SetRange(long long fstart, long long fend, long long fcount); 38 void SetCurrentPosition(long long fposition, long long fcount); 39 40 protected: 41 virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, 42 int alphaMod, QRect clipRegion); 43 44 virtual bool ParseElement( 45 const QString &filename, QDomElement &element, bool showWarnings); 46 virtual void CopyFrom(MythUIType *base); 47 virtual void CreateCopy(MythUIType *parent); 48 49 LayoutType m_layout; 50 EffectType m_effect; 51 52 unsigned char *m_drawMap; 53 int m_drawWidth; 54 int m_position; 55 56 QColor colorSet[5]; 57 58 int m_total; 59 int m_start; 60 int m_current; 61 62 void CalculatePosition(void); 63 }; 64 65 #endif -
mythtv/libs/libmythui/xmlparsebase.cpp
old new 28 28 #include "mythuispinbox.h" 29 29 #include "mythuicheckbox.h" 30 30 #include "mythuiprogressbar.h" 31 #include "mythuicutpointbar.h" 32 #include "mythuicutpointimage.h" 31 33 #include "mythuigroup.h" 32 34 #include "mythuiwebbrowser.h" 33 35 #include "mythuiguidegrid.h" … … void XMLParseBase::ParseChildren(const Q 246 248 type == "statetype" || 247 249 type == "clock" || 248 250 type == "progressbar" || 251 type == "cutpointbar" || 252 type == "cutpointimage" || 249 253 type == "webbrowser" || 250 254 type == "guidegrid" || 251 255 type == "shape") … … MythUIType *XMLParseBase::ParseUIType( 343 347 uitype = new MythUIClock(parent, name); 344 348 else if (type == "progressbar") 345 349 uitype = new MythUIProgressBar(parent, name); 350 else if (type == "cutpointbar") 351 uitype = new MythUICutPointBar(parent, name); 352 else if (type == "cutpointimage") 353 uitype = new MythUICutPointImage(parent, name); 346 354 else if (type == "webbrowser") 347 355 uitype = new MythUIWebBrowser(parent, name); 348 356 else if (type == "guidegrid") … … MythUIType *XMLParseBase::ParseUIType( 432 440 info.tagName() == "statetype" || 433 441 info.tagName() == "clock" || 434 442 info.tagName() == "progressbar" || 443 info.tagName() == "cutpointbar" || 444 info.tagName() == "cutpointimage" || 435 445 info.tagName() == "webbrowser" || 436 446 info.tagName() == "guidegrid" || 437 447 info.tagName() == "shape") … … bool XMLParseBase::doLoad(const QString 617 627 type == "window" || 618 628 type == "clock" || 619 629 type == "progressbar" || 630 type == "cutpointbar" || 631 type == "cutpointimage" || 620 632 type == "webbrowser" || 621 633 type == "guidegrid" || 622 634 type == "shape") -
new file mythbuild/mythtv/libs/libmythui/mythuicutpointimage.cpp
- + 1 2 // Own header 3 #include "mythuicutpointimage.h" 4 5 // C++ 6 #include <algorithm> 7 using namespace std; 8 9 // qt 10 #include <QDomDocument> 11 #include <QPainter> 12 #include <QSize> 13 #include <QColor> 14 15 // myth 16 #include "mythverbose.h" 17 #include "mythpainter.h" 18 #include "mythimage.h" 19 #include "mythmainwindow.h" 20 21 #ifndef FUNCTIONLOGGER 22 #define FUNCTIONLOGGER 23 #endif 24 25 MythUICutPointImage::MythUICutPointImage(MythUIType *parent, const QString &name) 26 : MythUIType(parent, name) 27 { 28 m_image = NULL; 29 30 m_cutStatus = 0; 31 m_highlightFrame = false; 32 m_framenumber = -1; 33 } 34 35 MythUICutPointImage::~MythUICutPointImage() 36 { 37 if (m_image) 38 { 39 m_image->DownRef(); 40 m_image = NULL; 41 } 42 } 43 44 void MythUICutPointImage::Reset() 45 { 46 if (m_image) 47 { 48 m_image->DownRef(); 49 m_image = NULL; 50 } 51 52 MythUIType::Reset(); 53 } 54 55 void MythUICutPointImage::DrawSelf(MythPainter *p, int xoffset, int yoffset, 56 int alphaMod, QRect clipRect) 57 { 58 //FUNCTIONLOGGER; 59 // if (m_image) 60 // VERBOSE(VB_GENERAL, QString("Has Image 1 (null? %1), has pixmap %2").arg(m_image->isNull()).arg(m_pm != NULL)); 61 // else 62 // VERBOSE(VB_GENERAL, QString("Has Image 0, has pixmap %1").arg(m_pm != NULL)); 63 64 QRect area = GetArea(); 65 area.translate(xoffset, yoffset); 66 67 if (!m_image || m_image->isNull()) 68 UpdateImage(); 69 70 if (m_image) { 71 p->DrawImage(area.x(), area.y(), m_image, alphaMod); 72 } 73 } 74 75 void MythUICutPointImage::SetPixmap(QPixmap * new_pmap, long long frame, int new_cutStatus) 76 { 77 //FUNCTIONLOGGER; 78 if (! new_pmap) 79 { 80 clearPixmap(); 81 return; 82 } 83 84 if (frame == m_framenumber) 85 { 86 // No change in pixmap (?) 87 setCutStatus(new_cutStatus); 88 return; 89 } 90 91 m_pmap = *new_pmap; 92 m_framenumber = frame; 93 94 if (new_cutStatus >= 0 && new_cutStatus <= 3) 95 m_cutStatus = new_cutStatus; 96 else 97 m_cutStatus = 0; 98 99 UpdateImage(); 100 SetRedraw(); 101 } 102 103 void MythUICutPointImage::clearPixmap(bool dorefresh) 104 { 105 if (! m_pmap.isNull()) 106 { 107 m_pmap = QPixmap(); 108 109 m_cutStatus = 0; 110 m_framenumber = -1; 111 UpdateImage(); 112 if (dorefresh) 113 SetRedraw(); 114 } 115 } 116 117 void MythUICutPointImage::setCutStatus(int new_cutStatus) 118 { 119 if (new_cutStatus == m_cutStatus) 120 return; 121 122 if (new_cutStatus >= 0 && new_cutStatus <= 3) 123 m_cutStatus = new_cutStatus; 124 else 125 m_cutStatus = 0; 126 127 UpdateImage(); 128 SetRedraw(); 129 } 130 131 132 //void MythUICutPointImage::DrawRect(const QRect &area,const QBrush &fillBrush, 133 // const QPen &linePen) 134 void MythUICutPointImage::UpdateImage() 135 { 136 if (m_image) 137 { 138 m_image->DownRef(); 139 m_image = NULL; 140 } 141 QRect area = GetArea(); 142 143 QImage image(QSize(area.width(), area.height()), QImage::Format_ARGB32); 144 QPainter painter(&image); 145 146 if (m_pmap.isNull()) 147 { 148 QRect tmparea(0, 0, area.width(), area.height()); 149 QColor drawcolor = QColor( 0, 0, 0); 150 painter.setBrush(QBrush(Qt::SolidPattern)); 151 painter.setPen(QPen(drawcolor, 2)); 152 painter.drawRect(tmparea); 153 } 154 else 155 { 156 QRect m_outer_border(0, 0, area.width(), area.height()); 157 QRect m_inner_border(1, 1, area.width()-2, area.height()-2); 158 painter.drawPixmap(0, 0, m_pmap); 159 160 painter.setRenderHint(QPainter::Antialiasing); 161 162 painter.setBrush(QBrush(Qt::NoBrush)); 163 painter.setPen(QPen(m_colorSet[0], 3)); 164 painter.drawRect(m_outer_border); 165 166 if (m_cutStatus > 0) 167 { 168 painter.setPen(QPen(m_colorSet[m_cutStatus], 3)); 169 painter.drawRect(m_inner_border); 170 painter.drawLine(m_inner_border.topLeft(), m_inner_border.bottomRight()); 171 painter.drawLine(m_inner_border.bottomLeft(), m_inner_border.topRight()); 172 } 173 if (m_highlightFrame) 174 { 175 // Overlay the image frame with the standard frame color 176 // This is used to highlight small frame #0 177 painter.setPen(QPen(m_highlightColor, 3)); 178 painter.drawRect(m_outer_border); 179 } 180 } 181 182 painter.end(); 183 184 m_image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage(); 185 m_image->UpRef(); 186 m_image->Assign(image); 187 } 188 189 bool MythUICutPointImage::ParseElement( 190 const QString &filename, QDomElement &element, bool showWarnings) 191 { 192 if (element.tagName() == "outlinecolor") 193 { 194 m_colorSet[0] = QColor(getFirstText(element)); 195 } 196 else if (element.tagName() == "cutcolor") 197 { 198 m_colorSet[1] = QColor(getFirstText(element)); 199 } 200 else if (element.tagName() == "cutpointcolor") 201 { 202 m_colorSet[2] = m_colorSet[3] = QColor(getFirstText(element)); 203 } 204 else if (element.tagName() == "highlightcolor") 205 { 206 m_highlightColor = QColor(getFirstText(element)); 207 m_highlightFrame = true; 208 } 209 else 210 { 211 return MythUIType::ParseElement(filename, element, showWarnings); 212 } 213 214 return true; 215 } 216 217 void MythUICutPointImage::CopyFrom(MythUIType *base) 218 { 219 MythUICutPointImage *shape = dynamic_cast<MythUICutPointImage *>(base); 220 if (!shape) 221 { 222 VERBOSE(VB_IMPORTANT, "ERROR, bad parsing"); 223 return; 224 } 225 226 m_image = shape->m_image; 227 if (m_image) 228 m_image->UpRef(); 229 230 m_pmap = shape->m_pmap ; 231 m_framenumber = shape->m_framenumber; 232 m_cutStatus = shape->m_cutStatus; 233 m_highlightFrame = shape->m_highlightFrame; 234 m_highlightColor = shape->m_highlightColor; 235 236 int i; 237 for (i = 0; i < 4; i++) 238 m_colorSet[i] = shape->m_colorSet[i]; 239 240 MythUIType::CopyFrom(base); 241 } 242 243 void MythUICutPointImage::CreateCopy(MythUIType *parent) 244 { 245 MythUICutPointImage *shape = new MythUICutPointImage(parent, objectName()); 246 shape->CopyFrom(this); 247 } 248 -
new file mythbuild/mythtv/libs/libmythui/mythuicutpointimage.h
- + 1 #ifndef MYTHUICUTPOINTIMAGE_H_ 2 #define MYTHUICUTPOINTIMAGE_H_ 3 4 // QT headers 5 #include <QColor> 6 #include <QPen> 7 #include <QBrush> 8 #include <QLinearGradient> 9 10 // Mythui headers 11 #include "mythuitype.h" 12 13 class MythImage; 14 15 class MPUBLIC MythUICutPointImage : public MythUIType 16 { 17 public: 18 MythUICutPointImage(MythUIType *parent, const QString &name); 19 ~MythUICutPointImage(); 20 21 void Reset(void); 22 23 void SetPixmap(QPixmap * new_pmap, long long frame, int new_cutStatus); 24 25 void clearPixmap(bool dorefresh=true); 26 void setCutStatus(int new_cutStatus); 27 28 protected: 29 virtual void DrawSelf(MythPainter *p, int xoffset, int yoffset, 30 int alphaMod, QRect clipRect); 31 32 virtual bool ParseElement( 33 const QString &filename, QDomElement &element, bool showWarnings); 34 virtual void CopyFrom(MythUIType *base); 35 virtual void CreateCopy(MythUIType *parent); 36 37 QLinearGradient parseGradient(const QDomElement &element); 38 39 void UpdateImage(); 40 41 private: 42 MythImage *m_image; 43 44 QPixmap m_pmap; 45 long long m_framenumber; // for consistency checking 46 int m_cutStatus; 47 QColor m_colorSet[4]; 48 bool m_highlightFrame; 49 QColor m_highlightColor; 50 }; 51 52 #endif
