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 { Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const {
QString title, artist, album, location; QString title, artist, album, location;
qint64 nanosec = -1; qint64 nanosec = -1;
int track_num = -1;
while (!reader->atEnd()) { while (!reader->atEnd()) {
QXmlStreamReader::TokenType type = reader->readNext(); QXmlStreamReader::TokenType type = reader->readNext();
@ -74,6 +75,13 @@ Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const {
if (!ok) { if (!ok) {
nanosec = -1; 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") { } else if (name == "image") {
// TODO: Fetch album covers. // TODO: Fetch album covers.
} else if (name == "info") { } else if (name == "info") {
@ -99,6 +107,7 @@ return_song:
song.set_artist(artist); song.set_artist(artist);
song.set_album(album); song.set_album(album);
song.set_length_nanosec(nanosec); song.set_length_nanosec(nanosec);
song.set_track(track_num);
return song; return song;
} }
@ -120,8 +129,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
StreamElement tracklist("trackList", &writer); StreamElement tracklist("trackList", &writer);
for (const Song& song : songs) { for (const Song& song : songs) {
QString filename_or_url = QString filename_or_url = URLOrFilename(song.url(), dir, path_type);
URLOrFilename(song.url(), dir, path_type);
StreamElement track("track", &writer); StreamElement track("track", &writer);
writer.writeTextElement("location", filename_or_url); writer.writeTextElement("location", filename_or_url);
@ -138,6 +146,9 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
writer.writeTextElement( writer.writeTextElement(
"duration", QString::number(song.length_nanosec() / kNsecPerMsec)); "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() QString art = song.art_manual().isEmpty() ? song.art_automatic()
: song.art_manual(); : 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(song_test.cpp false)
add_test_file(translations_test.cpp false) add_test_file(translations_test.cpp false)
add_test_file(utilities_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(closure_test.cpp false)
add_test_file(concurrentrun_test.cpp false) add_test_file(concurrentrun_test.cpp false)
add_test_file(zeroconf_test.cpp false) add_test_file(zeroconf_test.cpp false)

View File

@ -27,20 +27,18 @@
using ::testing::HasSubstr; using ::testing::HasSubstr;
class XSPFParserTest : public ::testing::Test { class XSPFParserTest : public ::testing::Test {};
};
TEST_F(XSPFParserTest, ParsesOneTrackFromXML) { TEST_F(XSPFParserTest, ParsesOneTrackFromXML) {
QByteArray data = QByteArray data =
"<playlist><trackList><track>" "<playlist><trackList><track>"
"<location>http://example.com/foo.mp3</location>" "<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>" "<title>Foo</title>"
"<creator>Bar</creator>" "<creator>Bar</creator>"
"<album>Baz</album>" "<album>Baz</album>"
"<duration>60000</duration>" "<duration>60000</duration>"
"<image>http://example.com/albumcover.jpg</image>" "<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>" "<info>http://example.com</info>"
"</track></trackList></playlist>"; "</track></trackList></playlist>";
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
@ -59,12 +57,12 @@ TEST_F(XSPFParserTest, ParsesOneTrackFromXML) {
TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) { TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
QByteArray data = QByteArray data =
"<playlist><trackList>" "<playlist><trackList>"
"<track>" "<track>"
"<location>http://example.com/foo.mp3</location>" "<location>http://example.com/foo.mp3</location>"
"</track>" "</track>"
"<track>" "<track>"
"<location>http://example.com/bar.mp3</location>" "<location>http://example.com/bar.mp3</location>"
"</track>" "</track>"
"</trackList></playlist>"; "</trackList></playlist>";
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
@ -80,13 +78,13 @@ TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
TEST_F(XSPFParserTest, IgnoresInvalidLength) { TEST_F(XSPFParserTest, IgnoresInvalidLength) {
QByteArray data = QByteArray data =
"<playlist><trackList><track>" "<playlist><trackList><track>"
"<location>http://example.com/foo.mp3</location>" "<location>http://example.com/foo.mp3</location>"
"<title>Foo</title>" "<title>Foo</title>"
"<creator>Bar</creator>" "<creator>Bar</creator>"
"<album>Baz</album>" "<album>Baz</album>"
"<duration>60000qwerty</duration>" "<duration>60000qwerty</duration>"
"<image>http://example.com/albumcover.jpg</image>" "<image>http://example.com/albumcover.jpg</image>"
"<info>http://example.com</info>" "<info>http://example.com</info>"
"</track></trackList></playlist>"; "</track></trackList></playlist>";
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
@ -96,6 +94,25 @@ TEST_F(XSPFParserTest, IgnoresInvalidLength) {
EXPECT_EQ(-1, songs[0].length_nanosec()); 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) { TEST_F(XSPFParserTest, SavesSong) {
QByteArray data; QByteArray data;
QBuffer buffer(&data); QBuffer buffer(&data);
@ -111,7 +128,8 @@ TEST_F(XSPFParserTest, SavesSong) {
songs << one; songs << one;
parser.Save(songs, &buffer); 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("<duration>123000</duration>"));
EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>")); EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>"));
EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>")); EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>"));
@ -128,13 +146,14 @@ TEST_F(XSPFParserTest, SavesLocalFile) {
one.set_title("foo"); one.set_title("foo");
one.set_length_nanosec(123 * kNsecPerSec); one.set_length_nanosec(123 * kNsecPerSec);
one.set_artist("bar"); one.set_artist("bar");
one.set_track(42);
SongList songs; SongList songs;
songs << one; songs << one;
parser.Save(songs, &buffer); 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("<duration>123000</duration>"));
EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>")); EXPECT_THAT(data.constData(), HasSubstr("<title>foo</title>"));
EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>")); EXPECT_THAT(data.constData(), HasSubstr("<creator>bar</creator>"));
EXPECT_THAT(data.constData(), HasSubstr("<trackNum>42</trackNum>"));
} }