1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2007 QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "PlaylistFileReader.h"
17
18 #include <QFile>
19 #include <QTextStream>
20 #include <QStringList>
21 #include <QFileInfo>
22 #include <QDir>
23
24 #include <iostream>
25
PlaylistFileReader(QString path)26 PlaylistFileReader::PlaylistFileReader(QString path) :
27 m_source(path),
28 m_file(nullptr)
29 {
30 if (!m_source.isAvailable()) {
31 m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
32 .arg(path);
33 return;
34 }
35 init();
36 }
37
PlaylistFileReader(FileSource source)38 PlaylistFileReader::PlaylistFileReader(FileSource source) :
39 m_source(source),
40 m_file(nullptr)
41 {
42 if (!m_source.isAvailable()) {
43 m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
44 .arg(source.getLocation());
45 return;
46 }
47 init();
48 }
49
~PlaylistFileReader()50 PlaylistFileReader::~PlaylistFileReader()
51 {
52 if (m_file) m_file->close();
53 delete m_file;
54 }
55
56 void
init()57 PlaylistFileReader::init()
58 {
59 if (!m_source.isAvailable()) return;
60
61 m_source.waitForData();
62
63 QString filename = m_source.getLocalFilename();
64
65 m_file = new QFile(filename);
66 bool good = false;
67
68 if (!m_file->exists()) {
69 m_error = QFile::tr("File \"%1\" does not exist")
70 .arg(m_source.getLocation());
71 } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
72 m_error = QFile::tr("Failed to open file \"%1\"")
73 .arg(m_source.getLocation());
74 } else {
75 good = true;
76 }
77
78 if (good) {
79 if (!m_source.isRemote()) {
80 m_basedir = QFileInfo(filename).dir().canonicalPath();
81 }
82 }
83
84 if (!good) {
85 delete m_file;
86 m_file = nullptr;
87 }
88 }
89
90 bool
isOK() const91 PlaylistFileReader::isOK() const
92 {
93 return (m_file != nullptr);
94 }
95
96 QString
getError() const97 PlaylistFileReader::getError() const
98 {
99 return m_error;
100 }
101
102 PlaylistFileReader::Playlist
load() const103 PlaylistFileReader::load() const
104 {
105 if (!m_file) return Playlist();
106
107 QTextStream in(m_file);
108 in.seek(0);
109
110 Playlist playlist;
111
112 while (!in.atEnd()) {
113
114 // cope with old-style Mac line endings (c.f. CSVFileReader)
115 // as well as DOS/Unix style
116
117 QString chunk = in.readLine();
118 QStringList lines = chunk.split('\r', QString::SkipEmptyParts);
119
120 for (int li = 0; li < lines.size(); ++li) {
121
122 QString line = lines[li];
123
124 if (line.startsWith("#")) continue;
125
126 // line is expected to be a URL or a file path. If it
127 // appears to be a local relative file path, then we
128 // should check whether it can be resolved relative to the
129 // location of the playlist file and, if so, do so.
130
131 if (!FileSource::isRemote(line)) {
132 if (QFileInfo(line).isRelative() && m_basedir != "") {
133 QString testpath = QDir(m_basedir).filePath(line);
134 if (QFileInfo(testpath).exists() &&
135 QFileInfo(testpath).isFile()) {
136 cerr << "Path \"" << line
137 << "\" is relative, resolving to \""
138 << testpath << "\""
139 << endl;
140 line = testpath;
141 }
142 }
143 }
144
145 playlist.push_back(line);
146 }
147 }
148
149 return playlist;
150 }
151
152 void
getSupportedExtensions(std::set<QString> & extensions)153 PlaylistFileReader::getSupportedExtensions(std::set<QString> &extensions)
154 {
155 extensions.insert("m3u");
156 }
157