Make M3U parser grab tags from file.
This commit is contained in:
parent
4219dfa718
commit
08416e2c51
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user