diff --git a/src/m3uparser.cpp b/src/m3uparser.cpp index 3659edbac..7ef384b8e 100644 --- a/src/m3uparser.cpp +++ b/src/m3uparser.cpp @@ -11,18 +11,19 @@ M3UParser::M3UParser(QIODevice* device, const QDir& directory, QObject* parent) const QList& M3UParser::Parse() { QString line = QString::fromLatin1(device_->readLine()); - if (line == "#EXTM3U") { + if (line.startsWith("#EXTM3U")) { // This is in extended M3U format. type_ = EXTENDED; line = QString::fromLatin1(device_->readLine()); } - do { + forever { if (line.startsWith('#')) { // Extended info or comment. if (type_ == EXTENDED && line.startsWith("#EXT")) { if (!ParseMetadata(line, ¤t_metadata_)) { qWarning() << "Failed to parse metadata: " << line; + continue; } } } else { @@ -30,10 +31,23 @@ const QList& M3UParser::Parse() { QUrl url; if (!ParseTrackLocation(line, &url)) { qWarning() << "Failed to parse location: " << line; + continue; } + Song song; + song.set_title(current_metadata_.title); + song.set_artist(current_metadata_.artist); + song.set_length(current_metadata_.length); + song.set_filename(url.toString()); + songs_ << song; + current_metadata_.artist.clear(); + current_metadata_.title.clear(); + current_metadata_.length = -1; + } + if (!device_->canReadLine()) { + break; } line = QString::fromLatin1(device_->readLine()); - } while (device_->canReadLine()); + } return songs_; } diff --git a/src/m3uparser.h b/src/m3uparser.h index 3b0d7f5dd..fa95a34e2 100644 --- a/src/m3uparser.h +++ b/src/m3uparser.h @@ -20,6 +20,7 @@ class M3UParser : public QObject { const SongList& Parse(); struct Metadata { + Metadata() : length(-1) {} QString artist; QString title; int length; diff --git a/tests/m3uparser_test.cpp b/tests/m3uparser_test.cpp index 34394329d..f6e808793 100644 --- a/tests/m3uparser_test.cpp +++ b/tests/m3uparser_test.cpp @@ -3,6 +3,8 @@ #include "m3uparser.h" +#include + class M3UParserTest : public ::testing::Test { protected: M3UParserTest() @@ -51,3 +53,37 @@ TEST_F(M3UParserTest, ParsesTrackLocationAbsoluteWindows) { EXPECT_EQ(QUrl("file:///c:/foo/bar.mp3"), url); } #endif // Q_OS_WIN32 + +TEST_F(M3UParserTest, ParsesSongsFromDevice) { + QByteArray data = "#EXTM3U\n" + "#EXTINF:123,Some Artist - Some Title\n" + "foo/bar/somefile.mp3\n"; + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + M3UParser parser(&buffer, QDir("somedir")); + const QList& songs = parser.Parse(); + ASSERT_EQ(1, songs.size()); + Song s = songs[0]; + EXPECT_EQ("Some Artist", s.artist()); + EXPECT_EQ("Some Title", s.title()); + EXPECT_EQ(123, s.length()); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, + "somedir/foo/bar/somefile.mp3", s.filename().toStdString()); +} + +TEST_F(M3UParserTest, ParsesNonExtendedM3U) { + QByteArray data = "foo/bar/somefile.mp3\n" + "baz/thing.mp3\n"; + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + M3UParser parser(&buffer, QDir("somedir")); + const QList& songs = parser.Parse(); + ASSERT_EQ(2, songs.size()); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, + "somedir/foo/bar/somefile.mp3", songs[0].filename().toStdString()); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, + "somedir/baz/thing.mp3", songs[1].filename().toStdString()); + EXPECT_EQ(-1, songs[0].length()); + EXPECT_EQ(-1, songs[1].length()); + EXPECT_TRUE(songs[0].artist().isEmpty()); +}