From kde-commits Sun Oct 31 10:28:10 2010 From: Pedro Lopez-Cabanillas Date: Sun, 31 Oct 2010 10:28:10 +0000 To: kde-commits Subject: extragear/multimedia/kmid/win Message-Id: <20101031102810.1EFB2AC89B () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=128852092128916 SVN commit 1191538 by pedrol: Windows backend. Fix for bug#255605: highlighted lyrics syllable randomly jumps when playing some songs having both Text and Lyric events. This bug hits all KMid backends. M +25 -0 song.cpp M +4 -0 song.h M +38 -12 winmidiobject.cpp M +1 -0 winmidiobject.h M +0 -2 winmidioutput.cpp --- trunk/extragear/multimedia/kmid/win/song.cpp #1191537:1191538 @@ -98,6 +98,16 @@ return m_packet.dwPacket; } + int SongEvent::getTag() const + { + return m_tag; + } + + void SongEvent::setTag(int tag) + { + m_tag = tag; + } + /* Song */ static inline bool eventLessThan(const SongEvent* s1, const SongEvent* s2) @@ -258,4 +268,19 @@ return false; } + void Song::discardRedundantEvents(TextType type) + { + if (!m_text[Lyric].empty()) { + QMutableListIterator it(*this); + while (it.hasNext()) { + SongEvent *ev = it.next(); + if ( ev->getType() == LYRIC_EVENT && + ev->getTag() != type ) { + it.remove(); + delete ev; } + } + } + } + +} --- trunk/extragear/multimedia/kmid/win/song.h #1191537:1191538 @@ -53,12 +53,15 @@ int getDataLength() const; DWORD getPacket() const; void setTick(qint64 time); + int getTag() const; + void setTag(int tag); private: qint64 m_ticktime; SongEventType m_type; WinMIDIPacket m_packet; QByteArray m_data; + int m_tag; }; class Song : public QList @@ -105,6 +108,7 @@ QTextCodec* getTextCodec() const { return m_codec; } QStringList getText(TextType type); QStringList getLyrics(qint64 time); + void discardRedundantEvents(TextType type); private: void appendStringToList(QStringList &list, QString &s, TextType type = Text); --- trunk/extragear/multimedia/kmid/win/winmidiobject.cpp #1191537:1191538 @@ -54,7 +54,9 @@ m_beatCount(0), m_lowestMidiNote(127), m_highestMidiNote(0), - m_currentTicks(0) + m_currentTicks(0), + m_lyricsEventType(Song::Text), + m_lastLyrics(0) { m_dbgState[LoadingState] = QLatin1String("Loading"); m_dbgState[StoppedState] = QLatin1String("Stopped"); @@ -95,7 +97,8 @@ QMutex m_openMutex; QMap m_textUserEvents; QMap m_dbgState; - + Song::TextType m_lyricsEventType; + qint64 m_lastLyrics; }; WinMIDIObject::WinMIDIObject(QObject *parent) : @@ -274,6 +277,8 @@ d->m_highestMidiNote = 0; d->m_currentTicks = 0; d->m_textUserEvents.clear(); + d->m_lyricsEventType = Song::Text; + d->m_lastLyrics = 0; for (int i=0; im_channelUsed[i] = false; d->m_channelEvents[i] = 0; @@ -299,8 +304,10 @@ if ( !d->m_song.isEmpty() && (d->m_state == PausedState || d->m_state == StoppedState) ) { d->m_out->setTimeDivision(d->m_song.getDivision()); - if (currentTime() == 0) + if (currentTime() == 0) { + d->m_lastLyrics = 0; d->m_out->setInitialTempo(d->m_initialTempo); + } d->m_out->sendResetMessage(); d->m_out->resetControllers(); sendInitialProgramChanges(); @@ -528,16 +535,13 @@ d->m_song.addMetaData(static_cast(type), data, tick); switch ( type ) { case Song::Lyric: + d->m_lyricsEventType = Song::Lyric; case Song::Text: if ((data.length() > 0) && (data[0] != '@') && (data[0] != '%') ) { - if (d->m_textUserEvents.contains(tick)) - d->m_textUserEvents[tick] += data; - else { - SongEvent *ev = new SongEvent( LYRIC_EVENT ); + SongEvent *ev = new SongEvent( LYRIC_EVENT, data ); + ev->setTag(type); appendEvent(ev); - d->m_textUserEvents[tick] = data; } - } break; case Song::TrackName: case Song::InstrumentName: @@ -631,7 +635,9 @@ d->m_engine->readFromFile(tmpFile); if (!d->m_song.isEmpty()) { addSongPadding(); + d->m_song.discardRedundantEvents(d->m_lyricsEventType); d->m_song.sort(); + buildTextUserEventsMap(); if (d->m_initialTempo == 0) { d->m_initialTempo = 500000; } @@ -718,7 +724,6 @@ void WinMIDIObject::emitShortEvSignals(qint64 ticks, const WinMIDIPacket& packet) { int value = 0; - QString txt; int type = MEVT_EVENTTYPE(packet.dwPacket); int parm = MEVT_EVENTPARM(packet.dwPacket); if ((type & MEVT_NOP) != 0) { @@ -727,7 +732,8 @@ emit tick(ticks); break; case 1: - if (d->m_textUserEvents.contains(ticks)) { + if (d->m_textUserEvents.contains(ticks) && ticks != d->m_lastLyrics) { + QString txt; if (d->m_codec == NULL) txt = QString::fromAscii(d->m_textUserEvents[ticks]); else @@ -735,6 +741,7 @@ txt.remove(QRegExp("[/\\\\]+")); txt.remove(QRegExp("[\r\n]+")); emit midiText(Song::Lyric, txt); + d->m_lastLyrics = ticks; } break; default: @@ -811,12 +818,31 @@ void WinMIDIObject::sendInitialProgramChanges() { - kDebug(); for (int i = 0; i < MIDI_CHANNELS; ++i) { int patch(d->m_channelPatches[i]); d->m_out->sendInitialProgram(i, patch); } } + + void WinMIDIObject::buildTextUserEventsMap() + { + d->m_textUserEvents.clear(); + SongIterator it(d->m_song); + while (it.hasNext()) { + SongEvent *ev = it.next(); + if (ev->getType() == LYRIC_EVENT && + ev->getTag() == d->m_lyricsEventType) { + qint64 tick = ev->getTick(); + QByteArray data = ev->getData(); + if (data.isEmpty()) + continue; + if (d->m_textUserEvents.contains(tick)) + d->m_textUserEvents[tick] += data; + else + d->m_textUserEvents[tick] = data; } + } + } +} #include "winmidiobject.moc" --- trunk/extragear/multimedia/kmid/win/winmidiobject.h #1191537:1191538 @@ -69,6 +69,7 @@ QVariant channelProperty(int channel, const QString& key); void sendInitialProgramChanges(); void emitShortEvSignals(qint64 ticks, const WinMIDIPacket& packet); + void buildTextUserEventsMap(); public Q_SLOTS: void setTickInterval(qint32 interval); --- trunk/extragear/multimedia/kmid/win/winmidioutput.cpp #1191537:1191538 @@ -607,7 +607,6 @@ d->m_locked[channel] = lock; if (lock) { d->m_lockedpgm[channel] = d->m_lastpgm[channel]; - kDebug() << channel << d->m_lastpgm[channel]; } emit lockedChanged( channel, lock ); } @@ -900,7 +899,6 @@ { int pgm(d->m_locked[chan] ? d->m_lockedpgm[chan] : program); if (pgm > -1) { - kDebug() << chan << pgm; WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & MIDI_CHANNEL_MASK); packet.data[1] = pgm;