Beispiel #1
0
addLyricsWindow::addLyricsWindow(QWidget *parent, QString songName) :
    QDialog(parent),
    ui(new Ui::addLyricsWindow)
{
    ui->setupUi(this);
    a_songName = songName;
    connect(ui->buttonCancel, SIGNAL(clicked()), this, SLOT(cancel()));
    connect(ui->buttonSave, SIGNAL(clicked()), this, SLOT(saveLyrics()));

}
Beispiel #2
0
void KNMusicLyricsManager::saveLyricsAndUpdateBackend(
        const KNMusicDetailInfo &detailInfo,
        const QString &content)
{
    //Save the lyrics.
    saveLyrics(detailInfo.textLists[Artist].toString(),
               detailInfo.textLists[Name].toString(),
               content);
    //Check whether the detail info is still the current one.
    if(detailInfo.filePath==m_detailInfo.filePath &&
            detailInfo.trackFilePath==m_detailInfo.trackFilePath &&
            detailInfo.trackIndex==m_detailInfo.trackIndex)
    {
        //Generate the data cache.
        QList<qint64> timeList;
        QStringList textList;
        //Use the parser to parse the file.
        if(m_parser->parseText(content, timeList, textList))
        {
            //Set the data to backend.
            m_backend->setLyricsData(timeList, textList);
        }
    }
}
Beispiel #3
0
void CKaraokeLyricsText::rescanLyrics()
{
  // Rescan fixes the following things:
  // - lyrics without spaces;
  // - lyrics without paragraphs
  std::vector<LyricTimingData> lyricdata;
  unsigned int spaces = 0, syllables = 0, paragraph_lines = 0, max_lines_per_paragraph = 0;

  // First get some statistics from the lyrics: number of paragraphs, number of spaces
  // and time difference between one line ends and second starts
  for ( unsigned int i = 0; i < m_lyrics.size(); i++ )
  {
    if ( m_lyrics[i].text.Find( " " ) != -1 )
      spaces++;

    if ( m_lyrics[i].flags & LYRICS_NEW_LINE )
      paragraph_lines++;

    if ( m_lyrics[i].flags & LYRICS_NEW_PARAGRAPH )
    {
      if ( max_lines_per_paragraph < paragraph_lines )
        max_lines_per_paragraph = paragraph_lines;

      paragraph_lines = 0;
    }

    syllables++;
  }

  // Second, add spaces if less than 5%, and rescan to gather more data.
  bool add_spaces = (syllables && (spaces * 100 / syllables < 5)) ? true : false;
  RESOLUTION res = g_graphicsContext.GetVideoResolution();
  float maxWidth = (float) g_settings.m_ResInfo[res].Overscan.right - g_settings.m_ResInfo[res].Overscan.left;

  CStdString line_text;
  int prev_line_idx = -1;
  int prev_line_timediff = -1;

  for ( unsigned int i = 0; i < m_lyrics.size(); i++ )
  {
    if ( add_spaces )
      m_lyrics[i].text += " ";

    // We split the lyric when it is end of line, end of array, or current string is too long already
    if ( i == (m_lyrics.size() - 1)
    || (m_lyrics[i+1].flags & (LYRICS_NEW_LINE | LYRICS_NEW_PARAGRAPH)) != 0
    || getStringWidth( line_text + m_lyrics[i].text ) >= maxWidth )
    {
      // End of line, or end of array. Add current string.
      line_text += m_lyrics[i].text;

      // Reparagraph if we're out of screen width
      if ( getStringWidth( line_text ) >= maxWidth )
        max_lines_per_paragraph = 0;

      LyricTimingData ld;
      ld.width = getStringWidth( line_text );
      ld.timediff = prev_line_timediff;
      ld.offset_start = prev_line_idx;

      // This piece extracts the first character of a new string and makes it uppercase in Unicode way
      CStdStringW temptext;
      g_charsetConverter.utf8ToW( line_text, temptext );

      // This is pretty ugly upper/lowercase for Russian unicode character set
      if ( temptext[0] >= 0x410 && temptext[0] <= 0x44F )
        ld.upper_start = temptext[0] <= 0x42F;
      else
      {
        CStdString lower = m_lyrics[i].text;
        lower.ToLower();
        ld.upper_start = (m_lyrics[i].text == lower);
      }

      lyricdata.push_back( ld );

      // Reset the params
      line_text = "";
      prev_line_idx = i + 1;
      prev_line_timediff = (i == m_lyrics.size() - 1) ? -1 : m_lyrics[i+1].timing - m_lyrics[i].timing;
    }
    else
    {
      // Handle incorrect lyrics with no line feeds in the condition statement above
      line_text += m_lyrics[i].text;
    }
  }

  // Now see if we need to re-paragraph. Basically we reasonably need a paragraph
  // to have no more than 8 lines
  if ( max_lines_per_paragraph == 0 || max_lines_per_paragraph > 8 )
  {
    // Reparagraph
    unsigned int paragraph_lines = 0;
    float total_width = 0;

    CLog::Log( LOGDEBUG, "CKaraokeLyricsText: lines need to be reparagraphed" );

    for ( unsigned int i = 0; i < lyricdata.size(); i++ )
    {
      // Is this the first line?
      if ( lyricdata[i].timediff == -1 )
      {
        total_width = lyricdata[i].width;
        continue;
      }

      // Do we merge the current line with previous? We do it if:
      // - there is a room on the screen for those lines combined
      // - the time difference between line ends and new starts is less than 1.5 sec
      // - the first character in the new line is not uppercase (i.e. new logic line)
      if ( m_mergeLines && total_width + lyricdata[i].width < maxWidth && !lyricdata[i].upper_start && lyricdata[i].timediff < 15 )
      {
        // Merge
        m_lyrics[ lyricdata[i].offset_start ].flags &= ~(LYRICS_NEW_LINE | LYRICS_NEW_PARAGRAPH);

        // Since we merged the line, add the extra space. It will be removed later if not necessary.
        m_lyrics[ lyricdata[i].offset_start ].text = " " + m_lyrics[ lyricdata[i].offset_start ].text;
        total_width += lyricdata[i].width;

//        CLog::Log(LOGERROR, "Line merged; diff %d width %g, start %d, offset %d, max %g",
//              lyricdata[i].timediff, lyricdata[i].width, lyricdata[i].upper_start, lyricdata[i].offset_start, maxWidth );
      }
      else
      {
        // Do not merge; reset width and add counter
        total_width = lyricdata[i].width;
        paragraph_lines++;

//        CLog::Log(LOGERROR, "Line not merged; diff %d width %g, start %d, offset %d, max %g",
//              lyricdata[i].timediff, lyricdata[i].width, lyricdata[i].upper_start, lyricdata[i].offset_start, maxWidth );
      }

      // Set paragraph
      if ( paragraph_lines > 3 )
      {
        m_lyrics[ lyricdata[i].offset_start ].flags &= ~LYRICS_NEW_LINE;
        m_lyrics[ lyricdata[i].offset_start ].flags |= LYRICS_NEW_PARAGRAPH;
        paragraph_lines = 0;
        line_text = "";
      }
    }
  }

  // Prepare a new first lyric entry with song name and artist.
  if ( m_songName.IsEmpty() )
  {
    m_songName = CUtil::GetFileName( getSongFile() );
    CUtil::RemoveExtension( m_songName );
  }

  // Split the lyrics into per-character array
  std::vector<Lyric> newlyrics;
  bool title_entry = false;

  if ( m_lyrics.size() > 0 && m_lyrics[0].timing >= 50 )
  {
    // Add a new title/artist entry
    Lyric ltitle;
    ltitle.flags = 0;
    ltitle.timing = 0;
    ltitle.text = m_songName;

    if ( !m_artist.IsEmpty() )
      ltitle.text += "[CR][CR]" + m_artist;

    newlyrics.push_back( ltitle );
    title_entry = true;
  }

  bool last_was_space = false;
  bool invalid_timing_reported = false;
  for ( unsigned int i = 0; i < m_lyrics.size(); i++ )
  {
    CStdStringW utf16;
    g_charsetConverter.utf8ToW( m_lyrics[i].text, utf16 );

    // Skip empty lyrics
    if ( utf16.size() == 0 )
      continue;

    // Use default timing for the last note
    unsigned int next_timing = m_lyrics[ i ].timing + m_delayAfter;

    if ( i < (m_lyrics.size() - 1) )
    {
      // Set the lenght for the syllable  to the length of prev syllable if:
      // - this is not the first lyric (as there is no prev otherwise)
      // - this is the last lyric on this line (otherwise use next);
      // - this is not the ONLY lyric on this line (otherwise the calculation is wrong)
      // - lyrics size is the same as previous (currently removed).
      if ( i > 0
      && m_lyrics[ i + 1 ].flags & (LYRICS_NEW_LINE | LYRICS_NEW_PARAGRAPH)
      && ! (m_lyrics[ i ].flags & (LYRICS_NEW_LINE | LYRICS_NEW_PARAGRAPH) ) )
//      && m_lyrics[ i ].text.size() == m_lyrics[ i -1 ].text.size() )
        next_timing = m_lyrics[ i ].timing + (m_lyrics[ i ].timing - m_lyrics[ i -1 ].timing );

      // Sanity check
      if ( m_lyrics[ i+1 ].timing < m_lyrics[ i ].timing )
      {
        if ( !invalid_timing_reported )
          CLog::Log( LOGERROR, "Karaoke lyrics normalizer: time went backward, enabling workaround" );

        invalid_timing_reported = true;
        m_lyrics[ i ].timing = m_lyrics[ i+1 ].timing;
      }

      if ( m_lyrics[ i+1 ].timing < next_timing )
        next_timing = m_lyrics[ i+1 ].timing;
    }

    // Calculate how many 1/10 seconds we have per lyric character
    double time_per_char = ((double) next_timing - m_lyrics[ i ].timing) / utf16.size();

    // Convert to characters
    for ( unsigned int j = 0; j < utf16.size(); j++ )
    {
      Lyric l;

      // Copy flags only to the first character
      if ( j == 0 )
        l.flags = m_lyrics[i].flags;
      else
        l.flags = 0;
      l.timing = (unsigned int) MathUtils::round_int( m_lyrics[ i ].timing + j * time_per_char );

      g_charsetConverter.wToUTF8( utf16.Mid( j, 1 ), l.text );

      if ( l.text == " " )
      {
        if ( last_was_space )
          continue;

        last_was_space = true;
      }
      else
        last_was_space = false;

      newlyrics.push_back( l );
    }
  }

  m_lyrics = newlyrics;

  // Set the NEW PARAGRAPH flag on the first real lyric entry since we changed it
  if ( title_entry )
    m_lyrics[1].flags |= LYRICS_NEW_PARAGRAPH;

  saveLyrics();
}