Support trackNum elements in XSPF.

Fixes #5093
This commit is contained in:
John Maguire 2015-10-28 16:17:52 +00:00
parent 240605a011
commit 84cc26f8b3
3 changed files with 59 additions and 29 deletions

View File

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

View File

@ -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)

View File

@ -27,20 +27,18 @@
using ::testing::HasSubstr;
class XSPFParserTest : public ::testing::Test {
};
class XSPFParserTest : public ::testing::Test {};
TEST_F(XSPFParserTest, ParsesOneTrackFromXML) {
QByteArray data =
"<playlist><trackList><track>"
"<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>"
"<creator>Bar</creator>"
"<album>Baz</album>"
"<duration>60000</duration>"
"<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>"
"<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>"
"<creator>Bar</creator>"
"<album>Baz</album>"
"<duration>60000</duration>"
"<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>"
"</track></trackList></playlist>";
QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly);
@ -59,12 +57,12 @@ TEST_F(XSPFParserTest, ParsesOneTrackFromXML) {
TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
QByteArray data =
"<playlist><trackList>"
"<track>"
"<location>http://example.com/foo.mp3</location>"
"</track>"
"<track>"
"<location>http://example.com/bar.mp3</location>"
"</track>"
"<track>"
"<location>http://example.com/foo.mp3</location>"
"</track>"
"<track>"
"<location>http://example.com/bar.mp3</location>"
"</track>"
"</trackList></playlist>";
QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly);
@ -80,13 +78,13 @@ TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
TEST_F(XSPFParserTest, IgnoresInvalidLength) {
QByteArray data =
"<playlist><trackList><track>"
"<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>"
"<creator>Bar</creator>"
"<album>Baz</album>"
"<duration>60000qwerty</duration>"
"<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>"
"<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>"
"<creator>Bar</creator>"
"<album>Baz</album>"
"<duration>60000qwerty</duration>"
"<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>"
"</track></trackList></playlist>";
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 =
"<playlist><trackList><track>"
"<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>"
"<creator>Bar</creator>"
"<album>Baz</album>"
"<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>"
"<trackNum>42</trackNum>"
"</track></trackList></playlist>";
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("<location>http://www.example.com/foo.mp3</location>"));
EXPECT_THAT(data.constData(),
HasSubstr("<location>http://www.example.com/foo.mp3</location>"));
EXPECT_THAT(data.constData(), HasSubstr("<duration>123000</duration>"));
EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>"));
EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>"));
@ -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("<location>file:///bar/foo.mp3</location>"));
EXPECT_THAT(data.constData(), HasSubstr("<location>/bar/foo.mp3</location>"));
EXPECT_THAT(data.constData(), HasSubstr("<duration>123000</duration>"));
EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>"));
EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>"));
EXPECT_THAT(data.constData(), HasSubstr("<trackNum>42</trackNum>"));
}