diff --git a/ChangeLog b/ChangeLog index 484fad9c9..b38951fa4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -76,6 +76,8 @@ 41. Cantata requires libMTP 1.1.0 or newer. 42. When displaying paths, convert to native separators, and remove trailing separator. When reading back entry, revert this process. +43. Fix tag editing, track re-organisation, and playback of non-MPD files via + HTTP server on windows. 1.1.3 ----- diff --git a/README b/README index 6a8b81074..08b29355b 100644 --- a/README +++ b/README @@ -710,6 +710,7 @@ The following debug values may be used: Context backdrop 128 Dynamic 256 Stream Fetching 512 + Http Server 1024 These values may be combined to enable multiple output. e.g. to enable MPD and covers logging: @@ -724,6 +725,14 @@ As of Cantata 1.2.0, all logging output is saved to a file. On Linux systems this will be ~/.cache/cantata/cantata.log For Windows this will be C:\Users\USERNAME\AppData\Local\mpd\cantata\cache\cantata.log +With windows builds, it is probably easier to ser the env var from a DOS +command prompt box. e.g.: + + 1. Run cmd.exe from start menu. + 2. cd c:\Program Files\Cantata + 3. set CANTATA_DEBUG=4 + 4. cantata.exe + NOTE: Debug logging will function regardless of whether you have created a Debug or Release build. diff --git a/gui/main.cpp b/gui/main.cpp index 52e9bdd3e..897aaf20b 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -53,6 +53,9 @@ #include "backdropcreator.h" #include "dynamic.h" #include "streamfetcher.h" +#ifdef TAGLIB_FOUND +#include "httpserver.h" +#endif #include #include @@ -64,7 +67,7 @@ static void cantataQtMsgHandler(QtMsgType, const char *msg) { QMutexLocker locker(&msgMutex); QFile f(Utils::cacheDir(QString(), true)+"cantata.log"); - if (f.open(QIODevice::WriteOnly|QIODevice::Append)) { + if (f.open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text)) { QTextStream stream(&f); if (firstMsg) { stream << "------------START------------" << endl; @@ -129,8 +132,9 @@ enum Debug { Dbg_Context_Backdrop = 0x0080, Dbg_Dynamic = 0x0100, Dbg_StreamFetching = 0x0200, + Dbg_HttpServer = 0x0400, - Dbg_All = 0x03FF + Dbg_All = 0x07FF }; int main(int argc, char *argv[]) @@ -214,6 +218,11 @@ int main(int argc, char *argv[]) if (dbg&Dbg_StreamFetching) { StreamFetcher::enableDebug(); } + #ifdef TAGLIB_FOUND + if (dbg&Dbg_HttpServer) { + HttpServer::enableDebug(); + } + #endif if (dbg&Dbg_All) { qInstallMsgHandler(cantataQtMsgHandler); } diff --git a/http/httpserver.cpp b/http/httpserver.cpp index a5528327f..faee7a6ce 100644 --- a/http/httpserver.cpp +++ b/http/httpserver.cpp @@ -35,6 +35,27 @@ K_GLOBAL_STATIC(HttpServer, instance) #endif +#include +static bool debugIsEnabled=false; +#define DBUG if (debugIsEnabled) qWarning() << "HttpServer" << __FUNCTION__ + +#ifdef Q_OS_WIN +static inline QString fixWindowsPath(const QString &f) +{ + return f.length()>3 && f.startsWith(QLatin1Char('/')) && QLatin1Char(':')==f.at(2) ? f.mid(1) : f; +} +#endif + +void HttpServer::enableDebug() +{ + debugIsEnabled=true; +} + +bool HttpServer::debugEnabled() +{ + return debugIsEnabled; +} + HttpServer * HttpServer::self() { #ifdef ENABLE_KDE_SUPPORT @@ -108,6 +129,7 @@ bool HttpServer::isOurs(const QString &url) const QByteArray HttpServer::encodeUrl(const Song &s) const { + DBUG << "song" << s.file << isAlive(); if (!isAlive()) { return QByteArray(); } @@ -154,13 +176,22 @@ QByteArray HttpServer::encodeUrl(const Song &s) const #if QT_VERSION >= 0x050000 url.setQuery(query); #endif + DBUG << "encoded as" << url.toString(); return url.toEncoded(); } QByteArray HttpServer::encodeUrl(const QString &file) const { + #ifdef Q_OS_WIN + QString f=fixWindowsPath(file); + DBUG << "file" << f; + Song s=Tags::read(f); + s.file=f; + #else + DBUG << "file" << file; Song s=Tags::read(file); s.file=file; + #endif return encodeUrl(s); } @@ -211,12 +242,16 @@ Song HttpServer::decodeUrl(const QUrl &url) const } s.file=url.path(); s.type=Song::CantataStream; + #ifdef Q_OS_WIN + s.file=fixWindowsPath(s.file); + #endif #if defined CDDB_FOUND || defined MUSICBRAINZ5_FOUND if (s.file.startsWith(QChar('/')+Song::constCddaProtocol)) { s.file=s.file.mid(1); s.type=Song::Cdda; } #endif + DBUG << s.file << s.albumArtist() << s.album << s.title; } return s; diff --git a/http/httpserver.h b/http/httpserver.h index 9be378985..323eba9e0 100644 --- a/http/httpserver.h +++ b/http/httpserver.h @@ -35,6 +35,9 @@ class QUrl; class HttpServer { public: + static void enableDebug(); + static bool debugEnabled(); + static HttpServer * self(); HttpServer() : thread(0), socket(0) { } diff --git a/http/httpsocket.cpp b/http/httpsocket.cpp index 302c19581..21d1f8e87 100644 --- a/http/httpsocket.cpp +++ b/http/httpsocket.cpp @@ -49,6 +49,8 @@ #include #include #endif +#include +#define DBUG if (HttpServer::debugEnabled()) qWarning() << "HttpSocket" << __FUNCTION__ static QString detectMimeType(const QString &file) { @@ -325,6 +327,7 @@ void HttpSocket::readClient() if (tokens.length()>=2 && "GET"==tokens[0]) { QStringList params = QString(socket->readAll()).split(QRegExp("[\r\n][\r\n]*")); + DBUG << "params" << params; if (!isFromMpd(params)) { return; } @@ -341,6 +344,7 @@ void HttpSocket::readClient() qint32 readBytesTo=0; getRange(params, readBytesFrom, readBytesTo); + DBUG << url.toString() << q.hasQueryItem("cantata"); if (q.hasQueryItem("cantata")) { Song song=HttpServer::self()->decodeUrl(url); if (song.isCdda()) { @@ -398,13 +402,13 @@ void HttpSocket::readClient() } } #endif - } else { - QFile f(url.path()); + } else if (!song.file.isEmpty()) { + QFile f(song.file); if (f.open(QIODevice::ReadOnly)) { qint32 totalBytes = f.size(); - writeMimeType(detectMimeType(url.path()), socket, totalBytes, true); + writeMimeType(detectMimeType(song.file), socket, totalBytes, true); ok=true; static const int constChunkSize=32768; char buffer[constChunkSize];