diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bfab14c5e..f5911a830 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -91,6 +91,7 @@ set(SOURCES playlist/songplaylistitem.cpp playlistparsers/asxparser.cpp + playlistparsers/asxiniparser.cpp playlistparsers/m3uparser.cpp playlistparsers/parserbase.cpp playlistparsers/playlistparser.cpp @@ -207,6 +208,7 @@ set(HEADERS playlist/songmimedata.h playlistparsers/asxparser.h + playlistparsers/asxiniparser.h playlistparsers/m3uparser.h playlistparsers/parserbase.h playlistparsers/playlistparser.h diff --git a/src/core/songloader.cpp b/src/core/songloader.cpp index 49f33506c..c571ee380 100644 --- a/src/core/songloader.cpp +++ b/src/core/songloader.cpp @@ -324,9 +324,19 @@ void SongLoader::ErrorMessageReceived(GstMessage* msg) { qDebug() << error->message; qDebug() << debugs; + QString message_str = error->message; + g_error_free(error); free(debugs); + if (state_ == WaitingForType && + message_str == "Could not determine type of stream.") { + // Don't give up - assume it's a playlist and see if one of our parsers can + // read it. + state_ = WaitingForMagic; + return; + } + StopTypefindAsync(false); } diff --git a/src/playlistparsers/asxiniparser.cpp b/src/playlistparsers/asxiniparser.cpp new file mode 100644 index 000000000..f9ae5e972 --- /dev/null +++ b/src/playlistparsers/asxiniparser.cpp @@ -0,0 +1,60 @@ +/* This file is part of Clementine. + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#include "asxiniparser.h" + +#include +#include + +AsxIniParser::AsxIniParser(QObject* parent) + : ParserBase(parent) +{ +} + +bool AsxIniParser::TryMagic(const QByteArray &data) const { + return data.toLower().contains("[reference]"); +} + +SongList AsxIniParser::Load(QIODevice *device, const QDir &dir) const { + SongList ret; + + while (!device->atEnd()) { + QString line = QString::fromUtf8(device->readLine()).trimmed(); + int equals = line.indexOf('='); + QString key = line.left(equals).toLower(); + QString value = line.mid(equals + 1); + + if (key.startsWith("ref")) { + Song song; + if (!ParseTrackLocation(value, dir, &song)) + qWarning() << "Failed to parse location: " << value; + ret << song; + } + } + + return ret; +} + +void AsxIniParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const { + QTextStream s(device); + s << "[Reference]" << endl; + + int n = 1; + foreach (const Song& song, songs) { + s << "Ref" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl; + ++n; + } +} diff --git a/src/playlistparsers/asxiniparser.h b/src/playlistparsers/asxiniparser.h new file mode 100644 index 000000000..fb0b90c10 --- /dev/null +++ b/src/playlistparsers/asxiniparser.h @@ -0,0 +1,37 @@ +/* This file is part of Clementine. + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef ASXINIPARSER_H +#define ASXINIPARSER_H + +#include "parserbase.h" + +class AsxIniParser : public ParserBase { + Q_OBJECT + +public: + AsxIniParser(QObject* parent = 0); + + QString name() const { return "ASX/INI"; } + QStringList file_extensions() const { return QStringList() << "asxini"; } + + bool TryMagic(const QByteArray &data) const; + + SongList Load(QIODevice *device, const QDir &dir = QDir()) const; + void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir()) const; +}; + +#endif // ASXINIPARSER_H diff --git a/src/playlistparsers/playlistparser.cpp b/src/playlistparsers/playlistparser.cpp index 33ad9e353..63cd01e15 100644 --- a/src/playlistparsers/playlistparser.cpp +++ b/src/playlistparsers/playlistparser.cpp @@ -19,6 +19,7 @@ #include "m3uparser.h" #include "plsparser.h" #include "asxparser.h" +#include "asxiniparser.h" #include @@ -31,6 +32,7 @@ PlaylistParser::PlaylistParser(QObject *parent) parsers_ << new XSPFParser(this); parsers_ << new PLSParser(this); parsers_ << new ASXParser(this); + parsers_ << new AsxIniParser(this); } QStringList PlaylistParser::file_extensions() const { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e11748cb5..a52fca962 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,10 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src) include_directories(${QT_QTTEST_INCLUDE_DIR}) +if(LIBGPOD_FOUND) + include_directories(${LIBGPOD_INCLUDE_DIRS}) +endif(LIBGPOD_FOUND) + set(GTEST-SOURCES ../3rdparty/gmock/gtest/src/gtest.cc ../3rdparty/gmock/gtest/src/gtest-death-test.cc @@ -87,6 +91,7 @@ endmacro (add_test_file) #add_test_file(albumcoverfetcher_test.cpp false) add_test_file(albumcovermanager_test.cpp true) add_test_file(asxparser_test.cpp false) +add_test_file(asxiniparser_test.cpp false) add_test_file(database_test.cpp false) add_test_file(fileformats_test.cpp false) add_test_file(librarybackend_test.cpp false) diff --git a/tests/asxiniparser_test.cpp b/tests/asxiniparser_test.cpp new file mode 100644 index 000000000..3b6cbb95f --- /dev/null +++ b/tests/asxiniparser_test.cpp @@ -0,0 +1,63 @@ +/* This file is part of Clementine. + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#include "test_utils.h" +#include "gmock/gmock-matchers.h" +#include "gtest/gtest.h" + +#include "playlistparsers/asxiniparser.h" +#include "playlistparsers/playlistparser.h" + +#include + +class AsxIniParserTest : public ::testing::Test { +protected: + AsxIniParser parser_; +}; + +TEST_F(AsxIniParserTest, ParsesBasicTrackList) { + QFile file(":/testdata/test.asxini"); + file.open(QIODevice::ReadOnly); + + SongList songs = parser_.Load(&file, QDir()); + ASSERT_EQ(2, songs.length()); + EXPECT_EQ("http://195.245.168.21/antena3?MSWMExt=.asf", songs[0].filename()); + EXPECT_EQ("http://195.245.168.21:80/antena3?MSWMExt=.asf", songs[1].filename()); + EXPECT_TRUE(songs[0].is_valid()); + EXPECT_TRUE(songs[1].is_valid()); +} + +TEST_F(AsxIniParserTest, Magic) { + QFile file(":/testdata/test.asxini"); + file.open(QIODevice::ReadOnly); + + EXPECT_TRUE(parser_.TryMagic(file.read(PlaylistParser::kMagicSize))); +} + +TEST_F(AsxIniParserTest, WritesBasicTrackList) { + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + + Song song; + song.set_filename("http://www.example.com/foo.mp3"); + + SongList songs; + songs << song; + + parser_.Save(songs, &buffer); + EXPECT_EQ("[Reference]\nRef1=http://www.example.com/foo.mp3\n", QString(data)); +} diff --git a/tests/data/test.asxini b/tests/data/test.asxini new file mode 100644 index 000000000..5e2f7ecd3 --- /dev/null +++ b/tests/data/test.asxini @@ -0,0 +1,3 @@ +[Reference] +Ref1=http://195.245.168.21/antena3?MSWMExt=.asf +Ref2=http://195.245.168.21:80/antena3?MSWMExt=.asf diff --git a/tests/data/testdata.qrc b/tests/data/testdata.qrc index 4ca45e0e0..d2e1bf0cd 100644 --- a/tests/data/testdata.qrc +++ b/tests/data/testdata.qrc @@ -14,5 +14,6 @@ test.asx secretagent.asx secretagent.pls + test.asxini