// Called by the video player to redraw the image. void MHIContext::UpdateOSD(InteractiveScreen *osdWindow, MythPainter *osdPainter) { if (!osdWindow || !osdPainter) return; QMutexLocker locker(&m_display_lock); m_updated = false; osdWindow->DeleteAllChildren(); // Copy all the display items into the display. list<MHIImageData*>::iterator it = m_display.begin(); for (int count = 0; it != m_display.end(); ++it, count++) { MHIImageData *data = *it; MythImage* image = osdPainter->GetFormatImage(); if (!image) continue; image->Assign(data->m_image); MythUIImage *uiimage = new MythUIImage(osdWindow, QString("itv%1") .arg(count)); if (uiimage) { uiimage->SetImage(image); uiimage->SetArea(MythRect(data->m_x, data->m_y, data->m_image.width(), data->m_image.height())); } image->DecrRef(); } osdWindow->OptimiseDisplayedArea(); // N.B. bypasses OSD class hence no expiry set osdWindow->SetVisible(true); }
MythUIType *MythUIEditBar::GetNew(MythUIShape *shape, MythUIImage *image) { QString name = QString("editbarimage_%1").arg(m_images.size()); if (shape) { MythUIShape *newshape = new MythUIShape(this, name); if (newshape) { newshape->CopyFrom(shape); newshape->SetVisible(true); m_images.append(newshape); return newshape; } } else if (image) { MythUIImage *newimage = new MythUIImage(this, name); if (newimage) { newimage->CopyFrom(image); newimage->SetVisible(true); m_images.append(newimage); return newimage; } } return NULL; }
void AirPlayPictureScreen::Init(void) { if (m_airplayImage) { if (!m_imageFilename.isEmpty()) { m_airplayImage->SetFilename(m_imageFilename); // Absolute path, http or SG url m_airplayImage->Load(); // By default the image is loaded in a background thread, use LoadNow() to load in foreground } else { // Will default to displaying whatever placeholder image is defined // in the xml by the themer, means we can show _something_ rather than // a big empty hole. Generally you always want to call Reset() in // these circumstances m_airplayImage->Reset(); } } if (m_airplayText) { if (!m_imageDescription.isEmpty()) { m_airplayText->SetText(m_imageDescription); } else { // Same as above, calling Reset() allows for a sane, themer defined //default to be displayed m_airplayText->Reset(); } } }
void SubtitleScreen::AddScaledImage(QImage &img, QRect &pos) { VideoOutput *vo = m_player->GetVideoOutput(); if (!vo) return; QRect scaled = vo->GetImageRect(pos); if (scaled.size() != pos.size()) { img = img.scaled(scaled.width(), scaled.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } MythPainter *osd_painter = vo->GetOSDPainter(); MythImage* image = NULL; if (osd_painter) image = osd_painter->GetFormatImage(); if (image) { image->Assign(img); MythUIImage *uiimage = new MythUIImage(this, "dvd_button"); if (uiimage) { m_refreshArea = true; uiimage->SetImage(image); uiimage->SetArea(MythRect(scaled)); } } }
bool MythUIStateType::AddImage(StateType type, MythImage *image) { if (m_ObjectsByState.contains((int)type) || !image) return false; MythUIImage *imType = new MythUIImage(this, "stateimage"); imType->SetImage(image); return AddObject(type, imType); }
bool MythUIStateType::AddImage(const QString &name, MythImage *image) { QString key = name.lower(); if (m_ObjectsByName.contains(key) || !image) return false; MythUIImage *imType = new MythUIImage(this, key); imType->SetImage(image); return AddObject(name, imType); }
void TeletextScreen::OptimiseDisplayedArea(void) { VideoOutput *vo = m_player->GetVideoOutput(); if (!vo) return; MythPainter *osd_painter = vo->GetOSDPainter(); if (!osd_painter) return; QHashIterator<int, QImage*> it(m_rowImages); while (it.hasNext()) { it.next(); MythImage* image = osd_painter->GetFormatImage(); if (!image || !it.value()) continue; int row = it.key(); image->Assign(*(it.value())); MythUIImage *uiimage = new MythUIImage(this, QString("ttrow%1") .arg(row)); if (uiimage) { uiimage->SetImage(image); uiimage->SetArea(MythRect(0, row * m_rowHeight, m_safeArea.width(), m_rowHeight * 2)); } } QRegion visible; QListIterator<MythUIType *> i(m_ChildrenList); while (i.hasNext()) { MythUIType *img = i.next(); visible = visible.united(img->GetArea()); } if (visible.isEmpty()) return; QRect bounding = visible.boundingRect(); bounding = bounding.translated(m_safeArea.topLeft()); bounding = m_safeArea.intersected(bounding); int left = m_safeArea.left() - bounding.left(); int top = m_safeArea.top() - bounding.top(); SetArea(MythRect(bounding)); i.toFront();; while (i.hasNext()) { MythUIType *img = i.next(); img->SetArea(img->GetArea().translated(left, top)); } }
bool MythUIStateType::AddImage(StateType type, MythImage *image) { if (m_ObjectsByState.contains((int)type) || !image) return false; QString name = QString("stateimage%1").arg(type); MythUIImage *imType = new MythUIImage(this, name); imType->SetImage(image); return AddObject(type, imType); }
void WeatherScreen::prepareWidget(MythUIType *widget) { MythUIImage *img; /* * Basically so we don't do it twice since some screens (Static Map) mess * with image dimensions */ if ((img = dynamic_cast<MythUIImage *>(widget))) { img->Load(); } }
bool MythUIStateType::AddImage(const QString &name, MythImage *image) { QString key = name.toLower(); if (m_ObjectsByName.contains(key) || !image) return false; // Uses name, not key which is lower case otherwise we break // inheritance MythUIImage *imType = new MythUIImage(this, name); imType->SetImage(image); return AddObject(key, imType); }
void OSD::SetGraph(const QString &window, const QString &graph, int64_t timecode) { MythScreenType *win = GetWindow(window); if (!win) return; MythUIImage *image = dynamic_cast<MythUIImage* >(win->GetChild(graph)); if (!image) return; MythImage* mi = m_parent->GetAudioGraph().GetImage(timecode); if (mi) image->SetImage(mi); }
void MythUIEditBar::AddBar(MythUIShape *shape, MythUIImage *image, const QRect &area) { MythUIType *add = GetNew(shape, image); if (add) { MythUIShape *shape = dynamic_cast<MythUIShape*>(add); MythUIImage *image = dynamic_cast<MythUIImage*>(add); if (shape) shape->SetCropRect(area.left(), area.top(), area.width(), area.height()); if (image) image->SetCropRect(area.left(), area.top(), area.width(), area.height()); add->SetPosition(area.left(), area.top()); } }
bool TrackInfoPopup::Create(void) { bool err = false; err = LoadWindowFromXML("music-ui.xml", "trackinfo_popup", this); if (!err) return false; // get map for current track MetadataMap metadataMap; m_metadata->toMap(metadataMap); // add the map from the next track MusicMetadata *nextMetadata = gPlayer->getNextMetadata(); if (nextMetadata) nextMetadata->toMap(metadataMap, "next"); SetTextFromMap(metadataMap); MythUIStateType *ratingState = dynamic_cast<MythUIStateType *>(GetChild("ratingstate")); if (ratingState) ratingState->DisplayState(QString("%1").arg(m_metadata->Rating())); MythUIImage *albumImage = dynamic_cast<MythUIImage *>(GetChild("coverart")); if (albumImage) { if (!m_metadata->getAlbumArtFile().isEmpty()) { albumImage->SetFilename(m_metadata->getAlbumArtFile()); albumImage->Load(); } } m_displayTimer = new QTimer(this); connect(m_displayTimer, SIGNAL(timeout()), this, SLOT(Close())); m_displayTimer->setSingleShot(true); m_displayTimer->start(MUSICINFOPOPUPTIME); return true; }
void MythUIProgressBar::CalculatePosition(void) { MythUIType *progressType = GetChild("progressimage"); if (!progressType) { LOG(VB_GENERAL, LOG_ERR, "Progress image doesn't exist"); return; } progressType->SetVisible(false); int total = m_total - m_start; int current = m_current - m_start; float percentage = 0.0; if (total <= 0 || current <= 0 || current > total) return; percentage = (float)current / (float)total; progressType->SetVisible(true); QRect fillArea = progressType->GetArea(); int height = fillArea.height(); int width = fillArea.width(); int x = fillArea.x(); int y = fillArea.y(); switch (m_effect) { case EffectReveal : if (m_layout == LayoutHorizontal) { width = (int)((float)fillArea.width() * percentage); } else { height = (int)((float)fillArea.height() * percentage); } break; case EffectSlide : if (m_layout == LayoutHorizontal) { int newwidth = (int)((float)fillArea.width() * percentage); x = width - newwidth; width = newwidth; } else { int newheight = (int)((float)fillArea.height() * percentage); y = height - newheight; height = newheight; } break; case EffectAnimate : // Not implemented yet break; } MythUIImage *progressImage = dynamic_cast<MythUIImage *>(progressType); MythUIShape *progressShape = dynamic_cast<MythUIShape *>(progressType); if (width <= 0) width = 1; if (height <= 0) height = 1; if (progressImage) progressImage->SetCropRect(x, y, width, height); else if (progressShape) progressShape->SetCropRect(x, y, width, height); SetRedraw(); }
void BDOverlayScreen::DisplayBDOverlay(BDOverlay *overlay) { if (!overlay || !m_player) return; if (!overlay->m_data) { m_overlayArea = overlay->m_position; SetArea(MythRect(m_overlayArea)); DeleteAllChildren(); m_overlayMap.clear(); SetRedraw(); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Initialised Size: %1x%2 (%3+%4) Plane: %5 Pts: %6") .arg(overlay->m_position.width()) .arg(overlay->m_position.height()) .arg(overlay->m_position.left()) .arg(overlay->m_position.top()) .arg(overlay->m_plane) .arg(overlay->m_pts)); BDOverlay::DeleteOverlay(overlay); return; } if (!m_overlayArea.isValid()) { LOG(VB_GENERAL, LOG_ERR, LOC + "Error: Overlay image submitted before initialisation."); } VideoOutput *vo = m_player->GetVideoOutput(); if (!vo) return; QRect rect = overlay->m_position; QString hash = QString("%1+%2+%3x%4") .arg(rect.left()).arg(rect.top()) .arg(rect.width()).arg(rect.height()); // remove if we already have this overlay if (m_overlayMap.contains(hash)) { LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Removing %1 (%2 left)") .arg(hash).arg(m_overlayMap.size())); MythUIImage *old = m_overlayMap.take(hash); DeleteChild(old); } // convert the overlay palette to ARGB uint32_t *origpalette = (uint32_t *)(overlay->m_palette); QVector<unsigned int> palette; for (int i = 0; i < 256; i++) { int y = (origpalette[i] >> 0) & 0xff; int cr = (origpalette[i] >> 8) & 0xff; int cb = (origpalette[i] >> 16) & 0xff; int a = (origpalette[i] >> 24) & 0xff; int r = int(y + 1.4022 * (cr - 128)); int b = int(y + 1.7710 * (cb - 128)); int g = int(1.7047 * y - (0.1952 * b) - (0.5647 * r)); if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; if (r > 0xff) r = 0xff; if (g > 0xff) g = 0xff; if (b > 0xff) b = 0xff; palette.push_back((a << 24) | (r << 16) | (g << 8) | b); } // convert the image to QImage QImage img(rect.size(), QImage::Format_Indexed8); memcpy(img.bits(), overlay->m_data, rect.width() * rect.height()); img.setColorTable(palette); img.convertToFormat(QImage::Format_ARGB32); // add to screen QRect scaled = vo->GetImageRect(rect); if (scaled.size() != rect.size()) { img = img.scaled(scaled.width(), scaled.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } MythPainter *osd_painter = vo->GetOSDPainter(); MythImage* image = NULL; if (osd_painter) image = osd_painter->GetFormatImage(); if (image) { image->Assign(img); MythUIImage *uiimage = new MythUIImage(this, "bdoverlay"); if (uiimage) { uiimage->SetImage(image); uiimage->SetArea(MythRect(scaled)); m_overlayMap.insert(hash, uiimage); LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Added %1 (%2 tot)") .arg(hash).arg(m_overlayMap.size())); } } SetRedraw(); BDOverlay::DeleteOverlay(overlay); }
void SubtitleScreen::DisplayAVSubtitles(void) { if (!m_player || !m_subreader) return; AVSubtitles* subs = m_subreader->GetAVSubtitles(); QMutexLocker lock(&(subs->lock)); if (subs->buffers.empty() && (kDisplayAVSubtitle != m_subtitleType)) return; VideoOutput *videoOut = m_player->GetVideoOutput(); VideoFrame *currentFrame = videoOut ? videoOut->GetLastShownFrame() : NULL; if (!currentFrame || !videoOut) return; float tmp = 0.0; QRect dummy; videoOut->GetOSDBounds(dummy, m_safeArea, tmp, tmp, tmp); while (!subs->buffers.empty()) { const AVSubtitle subtitle = subs->buffers.front(); if (subtitle.start_display_time > currentFrame->timecode) break; ClearDisplayedSubtitles(); subs->buffers.pop_front(); for (std::size_t i = 0; i < subtitle.num_rects; ++i) { AVSubtitleRect* rect = subtitle.rects[i]; bool displaysub = true; if (subs->buffers.size() > 0 && subs->buffers.front().end_display_time < currentFrame->timecode) { displaysub = false; } if (displaysub && rect->type == SUBTITLE_BITMAP) { // AVSubtitleRect's image data's not guaranteed to be 4 byte // aligned. QSize img_size(rect->w, rect->h); QRect img_rect(rect->x, rect->y, rect->w, rect->h); QRect display(rect->display_x, rect->display_y, rect->display_w, rect->display_h); // XSUB and some DVD/DVB subs are based on the original video // size before the video was converted. We need to guess the // original size and allow for the difference int right = rect->x + rect->w; int bottom = rect->y + rect->h; if (subs->fixPosition || (currentFrame->height < bottom) || (currentFrame->width < right)) { int sd_height = 576; if ((m_player->GetFrameRate() > 26.0f) && bottom <= 480) sd_height = 480; int height = ((currentFrame->height <= sd_height) && (bottom <= sd_height)) ? sd_height : ((currentFrame->height <= 720) && bottom <= 720) ? 720 : 1080; int width = ((currentFrame->width <= 720) && (right <= 720)) ? 720 : ((currentFrame->width <= 1280) && (right <= 1280)) ? 1280 : 1920; display = QRect(0, 0, width, height); } QRect scaled = videoOut->GetImageRect(img_rect, &display); QImage qImage(img_size, QImage::Format_ARGB32); for (int y = 0; y < rect->h; ++y) { for (int x = 0; x < rect->w; ++x) { const uint8_t color = rect->pict.data[0][y*rect->pict.linesize[0] + x]; const uint32_t pixel = *((uint32_t*)rect->pict.data[1]+color); qImage.setPixel(x, y, pixel); } } if (scaled.size() != img_size) { qImage = qImage.scaled(scaled.width(), scaled.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } MythPainter *osd_painter = videoOut->GetOSDPainter(); MythImage* image = NULL; if (osd_painter) image = osd_painter->GetFormatImage(); long long displayfor = subtitle.end_display_time - subtitle.start_display_time; if (displayfor == 0) displayfor = 60000; displayfor = (displayfor < 50) ? 50 : displayfor; long long late = currentFrame->timecode - subtitle.start_display_time; MythUIImage *uiimage = NULL; if (image) { image->Assign(qImage); QString name = QString("avsub%1").arg(i); uiimage = new MythUIImage(this, name); if (uiimage) { m_refreshArea = true; uiimage->SetImage(image); uiimage->SetArea(MythRect(scaled)); m_expireTimes.insert(uiimage, currentFrame->timecode + displayfor); } } if (uiimage) { LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display %1AV subtitle for %2ms") .arg(subtitle.forced ? "FORCED " : "") .arg(displayfor)); if (late > 50) LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("AV Sub was %1ms late").arg(late)); } } #ifdef USING_LIBASS else if (displaysub && rect->type == SUBTITLE_ASS) { InitialiseAssTrack(m_player->GetDecoder()->GetTrack(kTrackTypeSubtitle)); AddAssEvent(rect->ass); } #endif } m_subreader->FreeAVSubtitle(subtitle); } #ifdef USING_LIBASS RenderAssTrack(currentFrame->timecode); #endif }
/** * \copydoc MythUIType::CreateCopy() */ void MythUIImage::CreateCopy(MythUIType *parent) { QReadLocker updateLocker(&d->m_UpdateLock); MythUIImage *im = new MythUIImage(parent, objectName()); im->CopyFrom(this); }
void OSD::SetText(const QString &window, const InfoMap &map, OSDTimeout timeout) { MythScreenType *win = GetWindow(window); if (!win) return; if (map.contains("numstars")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("ratingstate")); if (state) state->DisplayState(map["numstars"]); } if (map.contains("tvstate")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("tvstate")); if (state) state->DisplayState(map["tvstate"]); } if (map.contains("videocodec")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("videocodec")); if (state) state->DisplayState(map["videocodec"]); } if (map.contains("videodescrip")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("videodescrip")); if (state) state->DisplayState(map["videodescrip"]); } if (map.contains("audiocodec")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("audiocodec")); if (state) state->DisplayState(map["audiocodec"]); } if (map.contains("audiochannels")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("audiochannels")); if (state) state->DisplayState(map["audiochannels"]); } if (map.contains("chanid")) { MythUIImage *icon = dynamic_cast<MythUIImage *> (win->GetChild("iconpath")); if (icon) { icon->Reset(); uint chanid = map["chanid"].toUInt(); QString iconpath; if (map.contains("iconpath")) iconpath = map["iconpath"]; else iconpath = ChannelUtil::GetIcon(chanid); if (!iconpath.isEmpty()) { QString iconurl = gCoreContext->GetMasterHostPrefix("ChannelIcons", iconpath); icon->SetFilename(iconurl); icon->Load(false); } } } if (map.contains("inetref")) { MythUIImage *cover = dynamic_cast<MythUIImage *> (win->GetChild("coverart")); if (cover && map.contains("coverartpath")) { QString coverpath = map["coverartpath"]; cover->SetFilename(coverpath); cover->Load(false); } MythUIImage *fanart = dynamic_cast<MythUIImage *> (win->GetChild("fanart")); if (fanart && map.contains("fanartpath")) { QString fanartpath = map["fanartpath"]; fanart->SetFilename(fanartpath); fanart->Load(false); } MythUIImage *banner = dynamic_cast<MythUIImage *> (win->GetChild("banner")); if (banner && map.contains("bannerpath")) { QString bannerpath = map["bannerpath"]; banner->SetFilename(bannerpath); banner->Load(false); } MythUIImage *screenshot = dynamic_cast<MythUIImage *> (win->GetChild("screenshot")); if (screenshot && map.contains("screenshotpath")) { QString screenshotpath = map["screenshotpath"]; screenshot->SetFilename(screenshotpath); screenshot->Load(false); } } if (map.contains("nightmode")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("nightmode")); if (state) state->DisplayState(map["nightmode"]); } if (map.contains("mediatype")) { MythUIStateType *state = dynamic_cast<MythUIStateType *> (win->GetChild("mediatype")); if (state) state->DisplayState(map["mediatype"]); } MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *>(win->GetChild("elapsedpercent")); if (bar) { int startts = map["startts"].toInt(); int endts = map["endts"].toInt(); int nowts = MythDate::current().toTime_t(); if (startts > nowts) { bar->SetUsed(0); } else if (endts < nowts) { bar->SetUsed(1000); } else { int duration = endts - startts; if (duration > 0) bar->SetUsed(1000 * (nowts - startts) / duration); else bar->SetUsed(0); } bar->SetVisible(startts > 0); bar->SetStart(0); bar->SetTotal(1000); } win->SetVisible(true); if (win == m_Dialog) { ChannelEditor *edit = dynamic_cast<ChannelEditor*>(m_Dialog); if (edit) edit->SetText(map); } else win->SetTextFromMap(map); SetExpiry(window, timeout); }