| 459 | Lyrics::Lyrics(MainVisual *parent) |
| 460 | { |
| 461 | m_pParent = parent; |
| 462 | |
| 463 | findFrontCover(); |
| 464 | |
| 465 | Decoder *dec = m_pParent->decoder(); |
| 466 | if (dec) |
| 467 | m_filename = dec->getFilename(); |
| 468 | |
| 469 | fps = 1; |
| 470 | } |
| 471 | |
| 472 | void Lyrics::findFrontCover(void) |
| 473 | { |
| 474 | // if a front cover image is available show that first |
| 475 | AlbumArtImages albumArt(m_pParent->metadata()); |
| 476 | if (albumArt.getImage(IT_FRONTCOVER)) |
| 477 | m_currImageType = IT_FRONTCOVER; |
| 478 | else |
| 479 | { |
| 480 | // not available so just show the first image available |
| 481 | if (albumArt.getImageCount() > 0) |
| 482 | m_currImageType = albumArt.getImageAt(0)->imageType; |
| 483 | else |
| 484 | m_currImageType = IT_UNKNOWN; |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | Lyrics::~Lyrics() |
| 489 | { |
| 490 | } |
| 491 | |
| 492 | void Lyrics::resize(const QSize &newsize) |
| 493 | { |
| 494 | m_size = newsize; |
| 495 | } |
| 496 | |
| 497 | bool Lyrics::process(VisualNode *node) |
| 498 | { |
| 499 | node = node; |
| 500 | return true; |
| 501 | } |
| 502 | |
| 503 | void Lyrics::handleKeyPress(const QString &action) |
| 504 | { |
| 505 | if (action == "DOWN") |
| 506 | { |
| 507 | if (m_start + 1 + m_visible_lines < int(m_lyrics.size())) |
| 508 | m_start++; |
| 509 | } |
| 510 | |
| 511 | if (action == "UP") |
| 512 | { |
| 513 | if (m_start != 0) |
| 514 | m_start--; |
| 515 | } |
| 516 | |
| 517 | if (action == "PAGEDOWN") |
| 518 | { |
| 519 | if (m_start + m_page_amount + m_visible_lines < int(m_lyrics.size())) |
| 520 | m_start += m_page_amount; |
| 521 | else |
| 522 | m_start = int(m_lyrics.size()) - m_page_amount; |
| 523 | } |
| 524 | |
| 525 | if (action == "PAGEUP") |
| 526 | { |
| 527 | if (m_start < m_page_amount) |
| 528 | m_start = 0; |
| 529 | else |
| 530 | m_start -= m_page_amount; |
| 531 | } |
| 532 | |
| 533 | if (action == "SELECT") |
| 534 | { |
| 535 | AlbumArtImages albumArt(m_pParent->metadata()); |
| 536 | int newType = m_currImageType; |
| 537 | |
| 538 | if (albumArt.getImageCount() > 0) |
| 539 | { |
| 540 | newType++; |
| 541 | |
| 542 | while (!albumArt.getImage((ImageType) newType)) |
| 543 | { |
| 544 | newType++; |
| 545 | if (newType == IT_LAST) |
| 546 | newType = IT_UNKNOWN; |
| 547 | } |
| 548 | } |
| 549 | |
| 550 | if (newType != m_currImageType) |
| 551 | { |
| 552 | m_currImageType = (ImageType) newType; |
| 553 | // force an update |
| 554 | m_cursize = QSize(0, 0); |
| 555 | } |
| 556 | } |
| 557 | } |
| 558 | |
| 559 | bool Lyrics::needsUpdate() |
| 560 | { |
| 561 | if (m_cursize != m_size) |
| 562 | return true; |
| 563 | |
| 564 | if (m_filename != m_pParent->decoder()->getFilename()) |
| 565 | { |
| 566 | m_filename = m_pParent->decoder()->getFilename(); |
| 567 | findFrontCover(); |
| 568 | return true; |
| 569 | } |
| 570 | |
| 571 | return false; |
| 572 | } |
| 573 | |
| 574 | void Lyrics::calculateScreenInfo(QPainter *p) |
| 575 | { |
| 576 | m_start = 0; |
| 577 | m_indentx = 0; |
| 578 | m_indenty = 0; |
| 579 | m_max_line_width = 0; |
| 580 | m_visible_lines = 0; |
| 581 | m_page_amount = 0; |
| 582 | m_font_height = 0; |
| 583 | m_lyrics_too_wide = false; |
| 584 | m_image_too_small = false; |
| 585 | |
| 586 | if (!m_lyrics.empty()) |
| 587 | { |
| 588 | p->setFont(GetMythUI()->GetMediumFont()); |
| 589 | |
| 590 | QFontMetrics fm(p->font()); |
| 591 | m_font_height = fm.height(); |
| 592 | |
| 593 | for (QVector<QString>::iterator i = m_lyrics.begin(); |
| 594 | i != m_lyrics.end(); i++) |
| 595 | { |
| 596 | int width = fm.width(*i); |
| 597 | if (width > m_max_line_width) m_max_line_width = width; |
| 598 | } |
| 599 | |
| 600 | m_indentx = int(0.03 * m_size.width()); |
| 601 | m_indenty = int(0.03 * m_size.height()); |
| 602 | |
| 603 | if ((m_max_line_width + 2 * m_indentx) > m_size.width()) |
| 604 | { |
| 605 | // Lyrics don't fit. Remove them. |
| 606 | m_lyrics.clear(); |
| 607 | m_max_line_width = 0; |
| 608 | m_indentx = 0; |
| 609 | m_indenty = 0; |
| 610 | m_lyrics_too_wide = true; |
| 611 | } |
| 612 | else |
| 613 | { |
| 614 | m_visible_lines = (m_size.height() - 2 * m_indenty) / m_font_height; |
| 615 | m_page_amount = m_visible_lines / 2; |
| 616 | if (m_size.width() < m_max_line_width + 3 * m_indentx + |
| 617 | int(0.1 * m_size.width())) |
| 618 | { |
| 619 | // Don't draw really small images |
| 620 | m_image_too_small = true; |
| 621 | } |
| 622 | } |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | bool Lyrics::draw(QPainter *p, const QColor &back) |
| 627 | { |
| 628 | if (!m_pParent->decoder()) |
| 629 | return false; |
| 630 | |
| 631 | // If the song has changed or the size, reload |
| 632 | if (needsUpdate()) |
| 633 | { |
| 634 | m_lyrics = m_pParent->metadata()->getUnsynchronizedLyrics(); |
| 635 | calculateScreenInfo(p); |
| 636 | |
| 637 | // Now we know how much room we have for the image. |
| 638 | QImage art(m_pParent->metadata()->getAlbumArt(m_currImageType)); |
| 639 | if (art.isNull()) |
| 640 | { |
| 641 | m_cursize = m_size; |
| 642 | m_image = QImage(); |
| 643 | } |
| 644 | else if (!m_image_too_small) |
| 645 | { |
| 646 | int height_adjustment = m_lyrics_too_wide ? m_font_height : 0; |
| 647 | QSize a_size(m_size.width() - m_max_line_width - 3 * m_indentx, |
| 648 | m_size.height() - height_adjustment); |
| 649 | m_image = art.scaled(a_size, Qt::KeepAspectRatio, |
| 650 | Qt::SmoothTransformation); |
| 651 | } |
| 652 | } |
| 653 | |
| 654 | if (m_image.isNull() && !m_image_too_small && m_lyrics.empty()) |
| 655 | { |
| 656 | drawWarning(p, back, m_size, QObject::tr("?")); |
| 657 | return true; |
| 658 | } |
| 659 | |
| 660 | p->fillRect(0, 0, m_size.width(), m_size.height(), back); |
| 661 | |
| 662 | // Paint the image |
| 663 | if (!m_image_too_small) |
| 664 | { |
| 665 | int xpos = (m_size.width() - m_max_line_width - |
| 666 | m_indentx - m_image.width()) /2; |
| 667 | int ypos = m_lyrics_too_wide ? 0 : |
| 668 | (m_size.height() - m_image.height()) / 2; |
| 669 | p->drawImage(xpos, ypos, m_image); |
| 670 | } |
| 671 | |
| 672 | // Paint the Lyrics |
| 673 | p->setFont(GetMythUI()->GetMediumFont()); |
| 674 | if (m_lyrics_too_wide) |
| 675 | { |
| 676 | // Lyrics are too wide to fit on the display. Just write "Lyrics" |
| 677 | // at the bottom on the display to indicate they are available. |
| 678 | QFontMetrics fm(p->font()); |
| 679 | QString l = "Lyrics"; |
| 680 | int width = fm.width(l); |
| 681 | int height = m_font_height; |
| 682 | int x = m_size.width() / 2 - width / 2; |
| 683 | int y = m_size.height() - height; |
| 684 | p->setPen(Qt::white); |
| 685 | p->drawText(x, y, width, height, Qt::AlignCenter, l); |
| 686 | } |
| 687 | else |
| 688 | { |
| 689 | int textWidth = m_max_line_width; |
| 690 | int textHeight = m_font_height * m_lyrics.size(); |
| 691 | int x = m_size.width() - m_max_line_width - m_indentx; |
| 692 | int y = m_indenty; |
| 693 | |
| 694 | int line = m_start; |
| 695 | for (int offset = 0; |
| 696 | line <= m_start + m_visible_lines-1 && line < int(m_lyrics.size()); |
| 697 | offset += m_font_height, line++) |
| 698 | { |
| 699 | QString l = m_lyrics[line] + "\n"; |
| 700 | p->setPen(Qt::white); |
| 701 | p->drawText(x, y + offset, textWidth, textHeight, Qt::AlignLeft, l); |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | // Store our new size |
| 706 | m_cursize = m_size; |
| 707 | |
| 708 | return true; |
| 709 | } |
| 710 | |
| 711 | static class LyricsFactory : public VisFactory |
| 712 | { |
| 713 | public: |
| 714 | const QString &name(void) const |
| 715 | { |
| 716 | static QString name("Lyrics"); |
| 717 | return name; |
| 718 | } |
| 719 | |
| 720 | uint plugins(QStringList *list) const |
| 721 | { |
| 722 | *list << name(); |
| 723 | return 1; |
| 724 | } |
| 725 | |
| 726 | VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const |
| 727 | { |
| 728 | (void)winid; |
| 729 | (void)pluginName; |
| 730 | return new Lyrics(parent); |
| 731 | } |
| 732 | }LyricsFactory; |
| 733 | |