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