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())); }
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); } } }
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(); }