Make M3U parser grab tags from file.

This commit is contained in:
John Maguire 2010-03-07 14:04:17 +00:00
parent 4219dfa718
commit 08416e2c51
3 changed files with 40 additions and 47 deletions

View File

@ -27,17 +27,16 @@ const QList<Song>& M3UParser::Parse() {
} }
} }
} else { } else {
// Track location.
QUrl url;
if (!ParseTrackLocation(line, &url)) {
qWarning() << "Failed to parse location: " << line;
continue;
}
Song song; Song song;
song.set_title(current_metadata_.title); song.set_title(current_metadata_.title);
song.set_artist(current_metadata_.artist); song.set_artist(current_metadata_.artist);
song.set_length(current_metadata_.length); song.set_length(current_metadata_.length);
song.set_filename(url.toString()); // Track location.
QString location;
if (!ParseTrackLocation(line, &song)) {
qWarning() << "Failed to parse location: " << line;
continue;
}
songs_ << song; songs_ << song;
current_metadata_.artist.clear(); current_metadata_.artist.clear();
current_metadata_.title.clear(); current_metadata_.title.clear();
@ -73,12 +72,12 @@ bool M3UParser::ParseMetadata(const QString& line, M3UParser::Metadata* metadata
return true; return true;
} }
bool M3UParser::ParseTrackLocation(const QString& line, QUrl* url) const { bool M3UParser::ParseTrackLocation(const QString& line, Song* song) const {
if (line.contains(QRegExp("^[a-z]+://"))) { if (line.contains(QRegExp("^[a-z]+://"))) {
// Looks like a url. // Looks like a url.
QUrl temp(line); QUrl temp(line);
if (temp.isValid()) { if (temp.isValid()) {
*url = temp; song->set_filename(temp.toString());
return true; return true;
} else { } else {
return false; return false;
@ -90,21 +89,12 @@ bool M3UParser::ParseTrackLocation(const QString& line, QUrl* url) const {
// Absolute path. // Absolute path.
// Fix windows \, eg. C:\foo -> C:/foo. // Fix windows \, eg. C:\foo -> C:/foo.
QString proper_path = QDir::fromNativeSeparators(line); QString proper_path = QDir::fromNativeSeparators(line);
// C:/foo -> /C:/foo. song->set_filename(proper_path);
if (!proper_path.startsWith('/')) {
proper_path.prepend("/");
}
*url = "file://" + proper_path;
return true;
} else { } else {
// Relative path. // Relative path.
QString proper_path = QDir::fromNativeSeparators(line); QString proper_path = QDir::fromNativeSeparators(line);
QString absolute_path = directory_.absoluteFilePath(proper_path); QString absolute_path = directory_.absoluteFilePath(proper_path);
// C:/foo -> /C:/foo. song->set_filename(absolute_path);
if (!absolute_path.startsWith('/')) {
absolute_path.prepend("/");
}
*url = "file://" + absolute_path;
return true;
} }
song->InitFromFile(song->filename(), -1);
} }

View File

@ -34,7 +34,7 @@ class M3UParser : public QObject {
}; };
bool ParseMetadata(const QString& line, Metadata* metadata) const; bool ParseMetadata(const QString& line, Metadata* metadata) const;
bool ParseTrackLocation(const QString& line, QUrl* url) const; bool ParseTrackLocation(const QString& line, Song* song) const;
FRIEND_TEST(M3UParserTest, ParsesMetadata); FRIEND_TEST(M3UParserTest, ParsesMetadata);
FRIEND_TEST(M3UParserTest, ParsesTrackLocation); FRIEND_TEST(M3UParserTest, ParsesTrackLocation);

View File

@ -1,5 +1,6 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "test_utils.h" #include "test_utils.h"
#include "mock_taglib.h"
#include "m3uparser.h" #include "m3uparser.h"
@ -7,11 +8,16 @@
class M3UParserTest : public ::testing::Test { class M3UParserTest : public ::testing::Test {
protected: protected:
static void SetUpTestCase() {
testing::DefaultValue<TagLib::String>::Set("foobarbaz");
}
M3UParserTest() M3UParserTest()
: parser_(NULL) { : parser_(NULL) {
} }
M3UParser parser_; M3UParser parser_;
MockFileRefFactory taglib_;
}; };
TEST_F(M3UParserTest, ParsesMetadata) { TEST_F(M3UParserTest, ParsesMetadata) {
@ -24,43 +30,40 @@ TEST_F(M3UParserTest, ParsesMetadata) {
} }
TEST_F(M3UParserTest, ParsesTrackLocation) { TEST_F(M3UParserTest, ParsesTrackLocation) {
taglib_.ExpectCall("/foo/bar.mp3", "foo", "bar", "baz");
Song song(&taglib_);
QString line("/foo/bar.mp3"); QString line("/foo/bar.mp3");
QUrl url; ASSERT_TRUE(parser_.ParseTrackLocation(line, &song));
ASSERT_TRUE(parser_.ParseTrackLocation(line, &url)); EXPECT_EQ("/foo/bar.mp3", song.filename());
EXPECT_EQ(QUrl("file:///foo/bar.mp3"), url); EXPECT_EQ("foo", song.title());
EXPECT_EQ("bar", song.artist());
EXPECT_EQ("baz", song.album());
} }
TEST_F(M3UParserTest, ParsesTrackLocationRelative) { TEST_F(M3UParserTest, ParsesTrackLocationRelative) {
taglib_.ExpectCall("/tmp/foo/bar.mp3", "foo", "bar", "baz");
M3UParser parser(NULL, QDir("/tmp")); M3UParser parser(NULL, QDir("/tmp"));
QString line("foo/bar.mp3"); QString line("foo/bar.mp3");
QUrl url; Song song(&taglib_);
ASSERT_TRUE(parser.ParseTrackLocation(line, &url)); ASSERT_TRUE(parser.ParseTrackLocation(line, &song));
EXPECT_EQ(QUrl("file:///tmp/foo/bar.mp3"), url); EXPECT_EQ("/tmp/foo/bar.mp3", song.filename());
EXPECT_EQ("foo", song.title());
} }
TEST_F(M3UParserTest, ParsesTrackLocationHttp) { TEST_F(M3UParserTest, ParsesTrackLocationHttp) {
QString line("http://example.com/foo/bar.mp3"); QString line("http://example.com/foo/bar.mp3");
QUrl url; Song song;
ASSERT_TRUE(parser_.ParseTrackLocation(line, &url)); ASSERT_TRUE(parser_.ParseTrackLocation(line, &song));
EXPECT_EQ(QUrl("http://example.com/foo/bar.mp3"), url); EXPECT_EQ("http://example.com/foo/bar.mp3", song.filename());
} }
#ifdef Q_OS_WIN32
TEST_F(M3UParserTest, ParsesTrackLocationAbsoluteWindows) {
QString line("c:/foo/bar.mp3");
QUrl url;
ASSERT_TRUE(parser_.ParseTrackLocation(line, &url));
EXPECT_EQ(QUrl("file:///c:/foo/bar.mp3"), url);
}
#endif // Q_OS_WIN32
TEST_F(M3UParserTest, ParsesSongsFromDevice) { TEST_F(M3UParserTest, ParsesSongsFromDevice) {
QByteArray data = "#EXTM3U\n" QByteArray data = "#EXTM3U\n"
"#EXTINF:123,Some Artist - Some Title\n" "#EXTINF:123,Some Artist - Some Title\n"
"foo/bar/somefile.mp3\n"; "http://foo.com/bar/somefile.mp3\n";
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
M3UParser parser(&buffer, QDir("somedir")); M3UParser parser(&buffer);
const QList<Song>& songs = parser.Parse(); const QList<Song>& songs = parser.Parse();
ASSERT_EQ(1, songs.size()); ASSERT_EQ(1, songs.size());
Song s = songs[0]; Song s = songs[0];
@ -68,21 +71,21 @@ TEST_F(M3UParserTest, ParsesSongsFromDevice) {
EXPECT_EQ("Some Title", s.title()); EXPECT_EQ("Some Title", s.title());
EXPECT_EQ(123, s.length()); EXPECT_EQ(123, s.length());
EXPECT_PRED_FORMAT2(::testing::IsSubstring, EXPECT_PRED_FORMAT2(::testing::IsSubstring,
"somedir/foo/bar/somefile.mp3", s.filename().toStdString()); "http://foo.com/bar/somefile.mp3", s.filename().toStdString());
} }
TEST_F(M3UParserTest, ParsesNonExtendedM3U) { TEST_F(M3UParserTest, ParsesNonExtendedM3U) {
QByteArray data = "foo/bar/somefile.mp3\n" QByteArray data = "http://foo.com/bar/somefile.mp3\n"
"baz/thing.mp3\n"; "http://baz.com/thing.mp3\n";
QBuffer buffer(&data); QBuffer buffer(&data);
buffer.open(QIODevice::ReadOnly); buffer.open(QIODevice::ReadOnly);
M3UParser parser(&buffer, QDir("somedir")); M3UParser parser(&buffer, QDir("somedir"));
const QList<Song>& songs = parser.Parse(); const QList<Song>& songs = parser.Parse();
ASSERT_EQ(2, songs.size()); ASSERT_EQ(2, songs.size());
EXPECT_PRED_FORMAT2(::testing::IsSubstring, EXPECT_PRED_FORMAT2(::testing::IsSubstring,
"somedir/foo/bar/somefile.mp3", songs[0].filename().toStdString()); "http://foo.com/bar/somefile.mp3", songs[0].filename().toStdString());
EXPECT_PRED_FORMAT2(::testing::IsSubstring, EXPECT_PRED_FORMAT2(::testing::IsSubstring,
"somedir/baz/thing.mp3", songs[1].filename().toStdString()); "http://baz.com/thing.mp3", songs[1].filename().toStdString());
EXPECT_EQ(-1, songs[0].length()); EXPECT_EQ(-1, songs[0].length());
EXPECT_EQ(-1, songs[1].length()); EXPECT_EQ(-1, songs[1].length());
EXPECT_TRUE(songs[0].artist().isEmpty()); EXPECT_TRUE(songs[0].artist().isEmpty());