diff --git a/src/playlistparsers/xspfparser.cpp b/src/playlistparsers/xspfparser.cpp index 186e4f612..c796d64b9 100644 --- a/src/playlistparsers/xspfparser.cpp +++ b/src/playlistparsers/xspfparser.cpp @@ -53,6 +53,7 @@ SongList XSPFParser::Load(QIODevice* device, const QString& playlist_path, Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const { QString title, artist, album, location; qint64 nanosec = -1; + int track_num = -1; while (!reader->atEnd()) { QXmlStreamReader::TokenType type = reader->readNext(); @@ -74,6 +75,13 @@ Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const { if (!ok) { nanosec = -1; } + } else if (name == "trackNum") { + const QString track_num_str = reader->readElementText(); + bool ok = false; + track_num = track_num_str.toInt(&ok); + if (!ok || track_num < 1) { + track_num = -1; + } } else if (name == "image") { // TODO: Fetch album covers. } else if (name == "info") { @@ -99,6 +107,7 @@ return_song: song.set_artist(artist); song.set_album(album); song.set_length_nanosec(nanosec); + song.set_track(track_num); return song; } @@ -120,8 +129,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir, StreamElement tracklist("trackList", &writer); for (const Song& song : songs) { - QString filename_or_url = - URLOrFilename(song.url(), dir, path_type); + QString filename_or_url = URLOrFilename(song.url(), dir, path_type); StreamElement track("track", &writer); writer.writeTextElement("location", filename_or_url); @@ -138,6 +146,9 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir, writer.writeTextElement( "duration", QString::number(song.length_nanosec() / kNsecPerMsec)); } + if (song.track() > 0) { + writer.writeTextElement("trackNum", QString::number(song.track())); + } QString art = song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f7d0a42ac..4227bb48e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -142,7 +142,7 @@ add_test_file(songplaylistitem_test.cpp false) add_test_file(song_test.cpp false) add_test_file(translations_test.cpp false) add_test_file(utilities_test.cpp false) -#add_test_file(xspfparser_test.cpp false) +add_test_file(xspfparser_test.cpp false) add_test_file(closure_test.cpp false) add_test_file(concurrentrun_test.cpp false) add_test_file(zeroconf_test.cpp false) diff --git a/tests/xspfparser_test.cpp b/tests/xspfparser_test.cpp index becdabbbc..0d3933ef3 100644 --- a/tests/xspfparser_test.cpp +++ b/tests/xspfparser_test.cpp @@ -27,20 +27,18 @@ using ::testing::HasSubstr; -class XSPFParserTest : public ::testing::Test { - -}; +class XSPFParserTest : public ::testing::Test {}; TEST_F(XSPFParserTest, ParsesOneTrackFromXML) { QByteArray data = "" - "http://example.com/foo.mp3" - "Foo" - "Bar" - "Baz" - "60000" - "http://example.com/albumcover.jpg" - "http://example.com" + "http://example.com/foo.mp3" + "Foo" + "Bar" + "Baz" + "60000" + "http://example.com/albumcover.jpg" + "http://example.com" ""; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); @@ -59,12 +57,12 @@ TEST_F(XSPFParserTest, ParsesOneTrackFromXML) { TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) { QByteArray data = "" - "" - "http://example.com/foo.mp3" - "" - "" - "http://example.com/bar.mp3" - "" + "" + "http://example.com/foo.mp3" + "" + "" + "http://example.com/bar.mp3" + "" ""; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); @@ -80,13 +78,13 @@ TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) { TEST_F(XSPFParserTest, IgnoresInvalidLength) { QByteArray data = "" - "http://example.com/foo.mp3" - "Foo" - "Bar" - "Baz" - "60000qwerty" - "http://example.com/albumcover.jpg" - "http://example.com" + "http://example.com/foo.mp3" + "Foo" + "Bar" + "Baz" + "60000qwerty" + "http://example.com/albumcover.jpg" + "http://example.com" ""; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); @@ -96,6 +94,25 @@ TEST_F(XSPFParserTest, IgnoresInvalidLength) { EXPECT_EQ(-1, songs[0].length_nanosec()); } +TEST_F(XSPFParserTest, ParsesTrackNum) { + QByteArray data = + "" + "http://example.com/foo.mp3" + "Foo" + "Bar" + "Baz" + "http://example.com/albumcover.jpg" + "http://example.com" + "42" + ""; + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + XSPFParser parser(nullptr); + SongList songs = parser.Load(&buffer); + ASSERT_EQ(1, songs.length()); + EXPECT_EQ(42, songs[0].track()); +} + TEST_F(XSPFParserTest, SavesSong) { QByteArray data; QBuffer buffer(&data); @@ -111,7 +128,8 @@ TEST_F(XSPFParserTest, SavesSong) { songs << one; parser.Save(songs, &buffer); - EXPECT_THAT(data.constData(), HasSubstr("http://www.example.com/foo.mp3")); + EXPECT_THAT(data.constData(), + HasSubstr("http://www.example.com/foo.mp3")); EXPECT_THAT(data.constData(), HasSubstr("123000")); EXPECT_THAT(data.constData(), HasSubstr("foo")); EXPECT_THAT(data.constData(), HasSubstr("bar")); @@ -128,13 +146,14 @@ TEST_F(XSPFParserTest, SavesLocalFile) { one.set_title("foo"); one.set_length_nanosec(123 * kNsecPerSec); one.set_artist("bar"); + one.set_track(42); SongList songs; songs << one; parser.Save(songs, &buffer); - EXPECT_THAT(data.constData(), HasSubstr("file:///bar/foo.mp3")); + EXPECT_THAT(data.constData(), HasSubstr("/bar/foo.mp3")); EXPECT_THAT(data.constData(), HasSubstr("123000")); EXPECT_THAT(data.constData(), HasSubstr("foo")); EXPECT_THAT(data.constData(), HasSubstr("bar")); + EXPECT_THAT(data.constData(), HasSubstr("42")); } -