Chris@297: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@297: 
Chris@297: /*
Chris@297:     Sonic Visualiser
Chris@297:     An audio file viewer and annotation editor.
Chris@297:     Centre for Digital Music, Queen Mary, University of London.
Chris@297:     This file copyright 2007 QMUL.
Chris@297:     
Chris@297:     This program is free software; you can redistribute it and/or
Chris@297:     modify it under the terms of the GNU General Public License as
Chris@297:     published by the Free Software Foundation; either version 2 of the
Chris@297:     License, or (at your option) any later version.  See the file
Chris@297:     COPYING included with this distribution for more information.
Chris@297: */
Chris@297: 
Chris@297: #include "PlaylistFileReader.h"
Chris@297: 
Chris@297: #include <QFile>
Chris@297: #include <QTextStream>
Chris@297: #include <QStringList>
Chris@440: #include <QFileInfo>
Chris@440: #include <QDir>
Chris@440: 
Chris@440: #include <iostream>
Chris@297: 
Chris@401: PlaylistFileReader::PlaylistFileReader(QString path) :
Chris@401:     m_source(path),
Chris@401:     m_file(0)
Chris@297: {
Chris@401:     if (!m_source.isAvailable()) {
Chris@401:         m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
Chris@401:             .arg(path);
Chris@401:         return;
Chris@401:     }
Chris@401:     init();
Chris@401: }
Chris@401: 
Chris@401: PlaylistFileReader::PlaylistFileReader(FileSource source) :
Chris@401:     m_source(source),
Chris@401:     m_file(0)
Chris@401: {
Chris@401:     if (!m_source.isAvailable()) {
Chris@401:         m_error = QFile::tr("File or URL \"%1\" could not be retrieved")
Chris@401:             .arg(source.getLocation());
Chris@401:         return;
Chris@401:     }
Chris@401:     init();
Chris@401: }
Chris@401: 
Chris@401: PlaylistFileReader::~PlaylistFileReader()
Chris@401: {
Chris@401:     if (m_file) m_file->close();
Chris@401:     delete m_file;
Chris@401: }
Chris@401: 
Chris@401: void
Chris@401: PlaylistFileReader::init()
Chris@401: {
Chris@401:     if (!m_source.isAvailable()) return;
Chris@401: 
Chris@401:     m_source.waitForData();
Chris@401: 
Chris@440:     QString filename = m_source.getLocalFilename();
Chris@440: 
Chris@440:     m_file = new QFile(filename);
Chris@297:     bool good = false;
Chris@297: 
Chris@297:     if (!m_file->exists()) {
Chris@401: 	m_error = QFile::tr("File \"%1\" does not exist")
Chris@401:             .arg(m_source.getLocation());
Chris@297:     } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
Chris@401: 	m_error = QFile::tr("Failed to open file \"%1\"")
Chris@401:             .arg(m_source.getLocation());
Chris@297:     } else {
Chris@297: 	good = true;
Chris@297:     }
Chris@297: 
Chris@440:     if (good) {
Chris@440:         if (!m_source.isRemote()) {
Chris@440:             m_basedir = QFileInfo(filename).dir().canonicalPath();
Chris@440:         }
Chris@440:     }
Chris@440: 
Chris@297:     if (!good) {
Chris@297: 	delete m_file;
Chris@297: 	m_file = 0;
Chris@297:     }
Chris@297: }
Chris@297: 
Chris@297: bool
Chris@297: PlaylistFileReader::isOK() const
Chris@297: {
Chris@297:     return (m_file != 0);
Chris@297: }
Chris@297: 
Chris@297: QString
Chris@297: PlaylistFileReader::getError() const
Chris@297: {
Chris@297:     return m_error;
Chris@297: }
Chris@297: 
Chris@297: PlaylistFileReader::Playlist
Chris@297: PlaylistFileReader::load() const
Chris@297: {
Chris@297:     if (!m_file) return Playlist();
Chris@297: 
Chris@297:     QTextStream in(m_file);
Chris@297:     in.seek(0);
Chris@297: 
Chris@297:     Playlist playlist;
Chris@297: 
Chris@297:     while (!in.atEnd()) {
Chris@297: 
Chris@297:         // cope with old-style Mac line endings (c.f. CSVFileReader)
Chris@297:         // as well as DOS/Unix style
Chris@297: 
Chris@297:         QString chunk = in.readLine();
Chris@297:         QStringList lines = chunk.split('\r', QString::SkipEmptyParts);
Chris@297:         
Chris@440:         for (int li = 0; li < lines.size(); ++li) {
Chris@297: 
Chris@297:             QString line = lines[li];
Chris@297: 
Chris@297:             if (line.startsWith("#")) continue;
Chris@297: 
Chris@440:             // line is expected to be a URL or a file path.  If it
Chris@440:             // appears to be a local relative file path, then we
Chris@440:             // should check whether it can be resolved relative to the
Chris@440:             // location of the playlist file and, if so, do so.
Chris@440: 
Chris@440:             if (!FileSource::isRemote(line)) {
Chris@440:                 if (QFileInfo(line).isRelative() && m_basedir != "") {
Chris@440:                     QString testpath = QDir(m_basedir).filePath(line);
Chris@440:                     if (QFileInfo(testpath).exists() &&
Chris@440:                         QFileInfo(testpath).isFile()) {
Chris@844:                         cerr << "Path \"" << line
Chris@440:                                   << "\" is relative, resolving to \""
Chris@686:                                   << testpath << "\""
Chris@843:                                   << endl;
Chris@440:                         line = testpath;
Chris@440:                     }
Chris@440:                 }
Chris@440:             }
Chris@440: 
Chris@297:             playlist.push_back(line);
Chris@297:         }
Chris@297:     }
Chris@297: 
Chris@297:     return playlist;
Chris@297: }
Chris@297: 
Chris@297: void
Chris@297: PlaylistFileReader::getSupportedExtensions(std::set<QString> &extensions)
Chris@297: {
Chris@297:     extensions.insert("m3u");
Chris@297: }