Includes, comments and bugfixes
- Fix includes - Use common regex (Song::kCoverRemoveDisc) for removing Disc/CD from album - Remove Disc/CD from album when creating hash - Make imobiledevice support compile - Fix setting device on windows
This commit is contained in:
@@ -15,6 +15,11 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
#include <QGenericArgument>
|
||||
|
||||
#include "closure.h"
|
||||
|
||||
#include "core/timeconstants.h"
|
||||
|
||||
@@ -18,15 +18,20 @@
|
||||
#ifndef CLOSURE_H
|
||||
#define CLOSURE_H
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QMetaObject>
|
||||
#include <QMetaMethod>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
|
||||
namespace _detail {
|
||||
@@ -40,11 +45,11 @@ class ClosureBase {
|
||||
virtual void Invoke() = 0;
|
||||
|
||||
// Tests only.
|
||||
ObjectHelper* helper() const;
|
||||
ObjectHelper *helper() const;
|
||||
|
||||
protected:
|
||||
explicit ClosureBase(ObjectHelper*);
|
||||
ObjectHelper* helper_;
|
||||
ObjectHelper *helper_;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ClosureBase);
|
||||
@@ -56,7 +61,7 @@ class ClosureBase {
|
||||
class ObjectHelper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ObjectHelper(QObject* parent, const char* signal, ClosureBase* closure);
|
||||
ObjectHelper(QObject *parent, const char *signal, ClosureBase *closure);
|
||||
|
||||
private slots:
|
||||
void Invoked();
|
||||
@@ -72,12 +77,12 @@ class ObjectHelper : public QObject {
|
||||
void Unpack(QList<QGenericArgument>*);
|
||||
|
||||
template <typename Arg>
|
||||
void Unpack(QList<QGenericArgument>* list, const Arg& arg) {
|
||||
void Unpack(QList<QGenericArgument> *list, const Arg &arg) {
|
||||
list->append(Q_ARG(Arg, arg));
|
||||
}
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
void Unpack(QList<QGenericArgument>* list, const Head& head, const Tail&... tail) {
|
||||
void Unpack(QList<QGenericArgument> *list, const Head &head, const Tail&... tail) {
|
||||
Unpack(list, head);
|
||||
Unpack(list, tail...);
|
||||
}
|
||||
@@ -86,16 +91,16 @@ template <typename... Args>
|
||||
class Closure : public ClosureBase {
|
||||
public:
|
||||
Closure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
QObject *sender,
|
||||
const char *signal,
|
||||
QObject *receiver,
|
||||
const char *slot,
|
||||
const Args&... args)
|
||||
: ClosureBase(new ObjectHelper(sender, signal, this)),
|
||||
// std::bind is the easiest way to store an argument list.
|
||||
function_(std::bind(&Closure<Args...>::Call, this, args...)),
|
||||
receiver_(receiver) {
|
||||
const QMetaObject* meta_receiver = receiver->metaObject();
|
||||
const QMetaObject *meta_receiver = receiver->metaObject();
|
||||
QByteArray normalised_slot = QMetaObject::normalizedSignature(slot + 1);
|
||||
const int index = meta_receiver->indexOfSlot(normalised_slot.constData());
|
||||
Q_ASSERT(index != -1);
|
||||
@@ -127,7 +132,7 @@ class Closure : public ClosureBase {
|
||||
}
|
||||
|
||||
std::function<void()> function_;
|
||||
QObject* receiver_;
|
||||
QObject *receiver_;
|
||||
QMetaMethod slot_;
|
||||
};
|
||||
|
||||
@@ -136,9 +141,9 @@ class SharedClosure : public Closure<Args...> {
|
||||
public:
|
||||
SharedClosure(
|
||||
QSharedPointer<T> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const char *signal,
|
||||
QObject *receiver,
|
||||
const char *slot,
|
||||
const Args&... args)
|
||||
: Closure<Args...>(
|
||||
sender.data(),
|
||||
@@ -155,8 +160,7 @@ class SharedClosure : public Closure<Args...> {
|
||||
|
||||
class CallbackClosure : public ClosureBase {
|
||||
public:
|
||||
CallbackClosure(QObject* sender, const char* signal,
|
||||
std::function<void()> callback);
|
||||
CallbackClosure(QObject *sender, const char *signal, std::function<void()> callback);
|
||||
|
||||
virtual void Invoke();
|
||||
|
||||
@@ -167,11 +171,11 @@ class CallbackClosure : public ClosureBase {
|
||||
} // namespace _detail
|
||||
|
||||
template <typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
_detail::ClosureBase *NewClosure(
|
||||
QObject *sender,
|
||||
const char *signal,
|
||||
QObject *receiver,
|
||||
const char *slot,
|
||||
const Args&... args) {
|
||||
return new _detail::Closure<Args...>(
|
||||
sender, signal, receiver, slot, args...);
|
||||
@@ -179,64 +183,64 @@ _detail::ClosureBase* NewClosure(
|
||||
|
||||
// QSharedPointer variant
|
||||
template <typename T, typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
_detail::ClosureBase *NewClosure(
|
||||
QSharedPointer<T> sender,
|
||||
const char* signal,
|
||||
QObject* receiver,
|
||||
const char* slot,
|
||||
const char *signal,
|
||||
QObject *receiver,
|
||||
const char *slot,
|
||||
const Args&... args) {
|
||||
return new _detail::SharedClosure<T, Args...>(
|
||||
sender, signal, receiver, slot, args...);
|
||||
}
|
||||
|
||||
_detail::ClosureBase* NewClosure(QObject* sender, const char* signal, std::function<void()> callback);
|
||||
_detail::ClosureBase *NewClosure(QObject *sender, const char *signal, std::function<void()> callback);
|
||||
|
||||
template <typename... Args>
|
||||
_detail::ClosureBase* NewClosure(QObject* sender, const char* signal, std::function<void(Args...)> callback, const Args&... args) {
|
||||
_detail::ClosureBase *NewClosure(QObject *sender, const char *signal, std::function<void(Args...)> callback, const Args&... args) {
|
||||
return NewClosure(sender, signal, std::bind(callback, args...));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
_detail::ClosureBase *NewClosure(
|
||||
QObject *sender,
|
||||
const char *signal,
|
||||
void (*callback)(Args...),
|
||||
const Args&... args) {
|
||||
return NewClosure(sender, signal, std::bind(callback, args...));
|
||||
}
|
||||
|
||||
template <typename T, typename Unused, typename... Args>
|
||||
_detail::ClosureBase* NewClosure(
|
||||
QObject* sender,
|
||||
const char* signal,
|
||||
T* receiver, Unused (T::*callback)(Args...),
|
||||
_detail::ClosureBase *NewClosure(
|
||||
QObject *sender,
|
||||
const char *signal,
|
||||
T *receiver, Unused (T::*callback)(Args...),
|
||||
const Args&... args) {
|
||||
return NewClosure(sender, signal, std::bind(callback, receiver, args...));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
_detail::ClosureBase* NewClosure(QFuture<T> future, QObject* receiver, const char* slot, const Args&... args) {
|
||||
QFutureWatcher<T>* watcher = new QFutureWatcher<T>;
|
||||
_detail::ClosureBase *NewClosure(QFuture<T> future, QObject *receiver, const char *slot, const Args&... args) {
|
||||
QFutureWatcher<T> *watcher = new QFutureWatcher<T>;
|
||||
watcher->setFuture(future);
|
||||
QObject::connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
|
||||
return NewClosure(watcher, SIGNAL(finished()), receiver, slot, args...);
|
||||
}
|
||||
|
||||
template <typename T, typename F, typename... Args>
|
||||
_detail::ClosureBase* NewClosure(QFuture<T> future, const F& callback, const Args&... args) {
|
||||
QFutureWatcher<T>* watcher = new QFutureWatcher<T>;
|
||||
_detail::ClosureBase *NewClosure(QFuture<T> future, const F &callback, const Args&... args) {
|
||||
QFutureWatcher<T> *watcher = new QFutureWatcher<T>;
|
||||
watcher->setFuture(future);
|
||||
QObject::connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
|
||||
return NewClosure(watcher, SIGNAL(finished()), callback, args...);
|
||||
}
|
||||
|
||||
void DoAfter(QObject* receiver, const char* slot, int msec);
|
||||
void DoAfter(QObject *receiver, const char *slot, int msec);
|
||||
void DoAfter(std::function<void()> callback, std::chrono::milliseconds msec);
|
||||
void DoInAMinuteOrSo(QObject* receiver, const char* slot);
|
||||
void DoInAMinuteOrSo(QObject *receiver, const char *slot);
|
||||
|
||||
template <typename R, typename P>
|
||||
void DoAfter(std::function<void()> callback, std::chrono::duration<R, P> duration) {
|
||||
QTimer* timer = new QTimer;
|
||||
QTimer *timer = new QTimer;
|
||||
timer->setSingleShot(true);
|
||||
NewClosure(timer, SIGNAL(timeout()), callback);
|
||||
QObject::connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
|
||||
|
||||
@@ -55,9 +55,7 @@ class ThreadFunctorBase : public QFutureInterface<ReturnType>, public QRunnable
|
||||
this->reportStarted();
|
||||
Q_ASSERT(thread_pool);
|
||||
QFuture<ReturnType> future = this->future();
|
||||
thread_pool->start(this, 0 /* priority: currently we do not support
|
||||
changing the priority. Might be added later
|
||||
if needed */);
|
||||
thread_pool->start(this, 0 /* priority: currently we do not support changing the priority. Might be added later if needed */);
|
||||
return future;
|
||||
}
|
||||
|
||||
@@ -67,8 +65,7 @@ class ThreadFunctorBase : public QFutureInterface<ReturnType>, public QRunnable
|
||||
template <typename ReturnType, typename... Args>
|
||||
class ThreadFunctor : public ThreadFunctorBase<ReturnType> {
|
||||
public:
|
||||
ThreadFunctor(std::function<ReturnType (Args...)> function,
|
||||
Args... args)
|
||||
ThreadFunctor(std::function<ReturnType (Args...)> function, Args... args)
|
||||
: function_(std::bind(function, args...)) {
|
||||
}
|
||||
|
||||
@@ -85,8 +82,7 @@ class ThreadFunctor : public ThreadFunctorBase<ReturnType> {
|
||||
template <typename... Args>
|
||||
class ThreadFunctor <void, Args...> : public ThreadFunctorBase<void> {
|
||||
public:
|
||||
ThreadFunctor(std::function<void (Args...)> function,
|
||||
Args... args)
|
||||
ThreadFunctor(std::function<void (Args...)> function, Args... args)
|
||||
: function_(std::bind(function, args...)) {
|
||||
}
|
||||
|
||||
@@ -107,30 +103,20 @@ namespace ConcurrentRun {
|
||||
|
||||
// Empty argument form.
|
||||
template <typename ReturnType>
|
||||
QFuture<ReturnType> Run(
|
||||
QThreadPool* threadpool,
|
||||
std::function<ReturnType ()> function) {
|
||||
QFuture<ReturnType> Run(QThreadPool* threadpool, std::function<ReturnType ()> function) {
|
||||
return (new ThreadFunctor<ReturnType>(function))->Start(threadpool);
|
||||
}
|
||||
|
||||
// Function object with arguments form.
|
||||
template <typename ReturnType, typename... Args>
|
||||
QFuture<ReturnType> Run(
|
||||
QThreadPool* threadpool,
|
||||
std::function<ReturnType (Args...)> function,
|
||||
const Args&... args) {
|
||||
return (new ThreadFunctor<ReturnType, Args...>(
|
||||
function, args...))->Start(threadpool);
|
||||
QFuture<ReturnType> Run(QThreadPool* threadpool, std::function<ReturnType (Args...)> function, const Args&... args) {
|
||||
return (new ThreadFunctor<ReturnType, Args...>(function, args...))->Start(threadpool);
|
||||
}
|
||||
|
||||
// Support passing C function pointers instead of function objects.
|
||||
template <typename ReturnType, typename... Args>
|
||||
QFuture<ReturnType> Run(
|
||||
QThreadPool* threadpool,
|
||||
ReturnType (*function) (Args...),
|
||||
const Args&... args) {
|
||||
return Run(
|
||||
threadpool, std::function<ReturnType (Args...)>(function), args...);
|
||||
QFuture<ReturnType> Run(QThreadPool* threadpool, ReturnType (*function) (Args...), const Args&... args) {
|
||||
return Run(threadpool, std::function<ReturnType (Args...)>(function), args...);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,21 +14,28 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QDateTime>
|
||||
#include <QIODevice>
|
||||
#include <QtMessageHandler>
|
||||
#include <QMessageLogContext>
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QStringList>
|
||||
#include <QtMessageHandler>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
namespace logging {
|
||||
@@ -75,7 +82,7 @@ static void MessageHandler(QtMsgType type, const QMessageLogContext &context, co
|
||||
default: level = Level_Debug; break;
|
||||
}
|
||||
|
||||
for (const QString& line : message.split('\n')) {
|
||||
for (const QString &line : message.split('\n')) {
|
||||
CreateLogger(level, "unknown", -1) << line.toLocal8Bit().constData();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#define LOGGING_H
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef QT_NO_DEBUG_STREAM
|
||||
@@ -61,30 +63,30 @@ enum Level {
|
||||
|
||||
void DumpStackTrace();
|
||||
|
||||
QString ParsePrettyFunction(const char* pretty_function);
|
||||
QString ParsePrettyFunction(const char *pretty_function);
|
||||
QDebug CreateLogger(Level level, const QString &class_name, int line);
|
||||
|
||||
QDebug CreateLoggerFatal(int line, const char* class_name);
|
||||
QDebug CreateLoggerError(int line, const char* class_name);
|
||||
QDebug CreateLoggerFatal(int line, const char *class_name);
|
||||
QDebug CreateLoggerError(int line, const char *class_name);
|
||||
|
||||
#ifdef QT_NO_WARNING_OUTPUT
|
||||
QNoDebug CreateLoggerWarning(int, const char*);
|
||||
#else
|
||||
QDebug CreateLoggerWarning(int line, const char* class_name);
|
||||
QDebug CreateLoggerWarning(int line, const char *class_name);
|
||||
#endif // QT_NO_WARNING_OUTPUT
|
||||
|
||||
#ifdef QT_NO_DEBUG_OUTPUT
|
||||
QNoDebug CreateLoggerInfo(int, const char*);
|
||||
QNoDebug CreateLoggerDebug(int, const char*);
|
||||
#else
|
||||
QDebug CreateLoggerInfo(int line, const char* class_name);
|
||||
QDebug CreateLoggerDebug(int line, const char* class_name);
|
||||
QDebug CreateLoggerInfo(int line, const char *class_name);
|
||||
QDebug CreateLoggerDebug(int line, const char *class_name);
|
||||
#endif // QT_NO_DEBUG_OUTPUT
|
||||
|
||||
|
||||
void GLog(const char* domain, int level, const char* message, void* user_data);
|
||||
void GLog(const char *domain, int level, const char *message, void *user_data);
|
||||
|
||||
extern const char* kDefaultLogLevels;
|
||||
extern const char *kDefaultLogLevels;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, std::chrono::seconds secs);
|
||||
|
||||
@@ -15,11 +15,15 @@
|
||||
*/
|
||||
|
||||
#include "messagehandler.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractSocket>
|
||||
#include <QLocalSocket>
|
||||
#include <QDataStream>
|
||||
#include <QIODevice>
|
||||
#include <QLocalSocket>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
_MessageHandlerBase::_MessageHandlerBase(QIODevice *device, QObject *parent)
|
||||
: QObject(parent),
|
||||
|
||||
@@ -18,21 +18,21 @@
|
||||
#ifndef MESSAGEHANDLER_H
|
||||
#define MESSAGEHANDLER_H
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <string>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QSemaphore>
|
||||
#include <QThread>
|
||||
#include <QIODevice>
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QLocalSocket>
|
||||
#include <QAbstractSocket>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/messagereply.h"
|
||||
|
||||
class QAbstractSocket;
|
||||
class QIODevice;
|
||||
class QLocalSocket;
|
||||
|
||||
#define QStringFromStdString(x) QString::fromUtf8(x.data(), x.size())
|
||||
#define DataCommaSizeFromQString(x) x.toUtf8().constData(), x.toUtf8().length()
|
||||
|
||||
@@ -45,27 +45,27 @@ class _MessageHandlerBase : public QObject {
|
||||
public:
|
||||
// device can be NULL, in which case you must call SetDevice before writing
|
||||
// any messages.
|
||||
_MessageHandlerBase(QIODevice* device, QObject* parent);
|
||||
_MessageHandlerBase(QIODevice *device, QObject *parent);
|
||||
|
||||
void SetDevice(QIODevice* device);
|
||||
void SetDevice(QIODevice *device);
|
||||
|
||||
// After this is true, messages cannot be sent to the handler any more.
|
||||
bool is_device_closed() const { return is_device_closed_; }
|
||||
|
||||
protected slots:
|
||||
void WriteMessage(const QByteArray& data);
|
||||
void WriteMessage(const QByteArray &data);
|
||||
void DeviceReadyRead();
|
||||
virtual void DeviceClosed();
|
||||
|
||||
protected:
|
||||
virtual bool RawMessageArrived(const QByteArray& data) = 0;
|
||||
virtual bool RawMessageArrived(const QByteArray &data) = 0;
|
||||
virtual void AbortAll() = 0;
|
||||
|
||||
protected:
|
||||
typedef bool (QAbstractSocket::*FlushAbstractSocket)();
|
||||
typedef bool (QLocalSocket::*FlushLocalSocket)();
|
||||
|
||||
QIODevice* device_;
|
||||
QIODevice *device_;
|
||||
FlushAbstractSocket flush_abstract_socket_;
|
||||
FlushLocalSocket flush_local_socket_;
|
||||
|
||||
@@ -82,7 +82,7 @@ protected:
|
||||
template <typename MT>
|
||||
class AbstractMessageHandler : public _MessageHandlerBase {
|
||||
public:
|
||||
AbstractMessageHandler(QIODevice* device, QObject* parent);
|
||||
AbstractMessageHandler(QIODevice *device, QObject *parent);
|
||||
~AbstractMessageHandler() { AbortAll(); }
|
||||
|
||||
typedef MT MessageType;
|
||||
@@ -90,27 +90,27 @@ public:
|
||||
|
||||
// Serialises the message and writes it to the socket. This version MUST be
|
||||
// called from the thread in which the AbstractMessageHandler was created.
|
||||
void SendMessage(const MessageType& message);
|
||||
void SendMessage(const MessageType &message);
|
||||
|
||||
// Serialises the message and writes it to the socket. This version may be
|
||||
// called from any thread.
|
||||
void SendMessageAsync(const MessageType& message);
|
||||
void SendMessageAsync(const MessageType &message);
|
||||
|
||||
// Sends the request message inside and takes ownership of the MessageReply.
|
||||
// The MessageReply's Finished() signal will be emitted when a reply arrives
|
||||
// with the same ID. Must be called from my thread.
|
||||
void SendRequest(ReplyType* reply);
|
||||
void SendRequest(ReplyType *reply);
|
||||
|
||||
// Sets the "id" field of reply to the same as the request, and sends the
|
||||
// reply on the socket. Used on the worker side.
|
||||
void SendReply(const MessageType& request, MessageType* reply);
|
||||
void SendReply(const MessageType &request, MessageType *reply);
|
||||
|
||||
protected:
|
||||
// Called when a message is received from the socket.
|
||||
virtual void MessageArrived(const MessageType& message) {}
|
||||
virtual void MessageArrived(const MessageType &message) {}
|
||||
|
||||
// _MessageHandlerBase
|
||||
bool RawMessageArrived(const QByteArray& data);
|
||||
bool RawMessageArrived(const QByteArray &data);
|
||||
void AbortAll();
|
||||
|
||||
private:
|
||||
@@ -118,12 +118,11 @@ private:
|
||||
};
|
||||
|
||||
template <typename MT>
|
||||
AbstractMessageHandler<MT>::AbstractMessageHandler(QIODevice* device,
|
||||
QObject* parent)
|
||||
AbstractMessageHandler<MT>::AbstractMessageHandler(QIODevice *device, QObject *parent)
|
||||
: _MessageHandlerBase(device, parent) {}
|
||||
|
||||
template <typename MT>
|
||||
void AbstractMessageHandler<MT>::SendMessage(const MessageType& message) {
|
||||
void AbstractMessageHandler<MT>::SendMessage(const MessageType &message) {
|
||||
Q_ASSERT(QThread::currentThread() == thread());
|
||||
|
||||
std::string data = message.SerializeAsString();
|
||||
@@ -131,33 +130,32 @@ void AbstractMessageHandler<MT>::SendMessage(const MessageType& message) {
|
||||
}
|
||||
|
||||
template <typename MT>
|
||||
void AbstractMessageHandler<MT>::SendMessageAsync(const MessageType& message) {
|
||||
void AbstractMessageHandler<MT>::SendMessageAsync(const MessageType &message) {
|
||||
std::string data = message.SerializeAsString();
|
||||
metaObject()->invokeMethod(this, "WriteMessage", Qt::QueuedConnection,
|
||||
Q_ARG(QByteArray, QByteArray(data.data(), data.size())));
|
||||
}
|
||||
|
||||
template<typename MT>
|
||||
void AbstractMessageHandler<MT>::SendRequest(ReplyType* reply) {
|
||||
void AbstractMessageHandler<MT>::SendRequest(ReplyType *reply) {
|
||||
pending_replies_[reply->id()] = reply;
|
||||
SendMessage(reply->request_message());
|
||||
}
|
||||
|
||||
template<typename MT>
|
||||
void AbstractMessageHandler<MT>::SendReply(const MessageType& request,
|
||||
MessageType* reply) {
|
||||
void AbstractMessageHandler<MT>::SendReply(const MessageType &request, MessageType *reply) {
|
||||
reply->set_id(request.id());
|
||||
SendMessage(*reply);
|
||||
}
|
||||
|
||||
template<typename MT>
|
||||
bool AbstractMessageHandler<MT>::RawMessageArrived(const QByteArray& data) {
|
||||
bool AbstractMessageHandler<MT>::RawMessageArrived(const QByteArray &data) {
|
||||
MessageType message;
|
||||
if (!message.ParseFromArray(data.constData(), data.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReplyType* reply = pending_replies_.take(message.id());
|
||||
ReplyType *reply = pending_replies_.take(message.id());
|
||||
|
||||
if (reply) {
|
||||
// This is a reply to a message that we created earlier.
|
||||
@@ -171,7 +169,7 @@ bool AbstractMessageHandler<MT>::RawMessageArrived(const QByteArray& data) {
|
||||
|
||||
template<typename MT>
|
||||
void AbstractMessageHandler<MT>::AbortAll() {
|
||||
for (ReplyType* reply : pending_replies_) {
|
||||
for (ReplyType *reply : pending_replies_) {
|
||||
reply->Abort();
|
||||
}
|
||||
pending_replies_.clear();
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
#include "messagereply.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
_MessageReplyBase::_MessageReplyBase(QObject *parent)
|
||||
: QObject(parent), finished_(false), success_(false) {}
|
||||
|
||||
|
||||
@@ -18,26 +18,26 @@
|
||||
#ifndef MESSAGEREPLY_H
|
||||
#define MESSAGEREPLY_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QSemaphore>
|
||||
#include <QString>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
// Base QObject for a reply future class that is returned immediately for
|
||||
// requests that will occur in the background. Similar to QNetworkReply.
|
||||
// Use MessageReply instead.
|
||||
// Base QObject for a reply future class that is returned immediately for requests that will occur in the background.
|
||||
// Similar to QNetworkReply. Use MessageReply instead.
|
||||
class _MessageReplyBase : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
_MessageReplyBase(QObject* parent = nullptr);
|
||||
_MessageReplyBase(QObject *parent = nullptr);
|
||||
|
||||
virtual int id() const = 0;
|
||||
bool is_finished() const { return finished_; }
|
||||
bool is_successful() const { return success_; }
|
||||
|
||||
// Waits for the reply to finish by waiting on a semaphore. Never call this
|
||||
// from the MessageHandler's thread or it will block forever.
|
||||
// Waits for the reply to finish by waiting on a semaphore. Never call this from the MessageHandler's thread or it will block forever.
|
||||
// Returns true if the call was successful.
|
||||
bool WaitForFinished();
|
||||
|
||||
@@ -58,7 +58,7 @@ protected:
|
||||
template <typename MessageType>
|
||||
class MessageReply : public _MessageReplyBase {
|
||||
public:
|
||||
MessageReply(const MessageType& request_message, QObject* parent = nullptr);
|
||||
MessageReply(const MessageType& request_message, QObject *parent = nullptr);
|
||||
|
||||
int id() const { return request_message_.id(); }
|
||||
const MessageType& request_message() const { return request_message_; }
|
||||
@@ -73,8 +73,7 @@ private:
|
||||
|
||||
|
||||
template<typename MessageType>
|
||||
MessageReply<MessageType>::MessageReply(const MessageType& request_message,
|
||||
QObject* parent)
|
||||
MessageReply<MessageType>::MessageReply(const MessageType& request_message, QObject *parent)
|
||||
: _MessageReplyBase(parent)
|
||||
{
|
||||
request_message_.MergeFrom(request_message);
|
||||
@@ -94,4 +93,3 @@ void MessageReply<MessageType>::SetReply(const MessageType& message) {
|
||||
}
|
||||
|
||||
#endif // MESSAGEREPLY_H
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "waitforsignal.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QEventLoop>
|
||||
|
||||
void WaitForSignal(QObject *sender, const char *signal) {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "workerpool.h"
|
||||
|
||||
_WorkerPoolBase::_WorkerPoolBase(QObject *parent) : QObject(parent) {}
|
||||
|
||||
@@ -18,32 +18,37 @@
|
||||
#ifndef WORKERPOOL_H
|
||||
#define WORKERPOOL_H
|
||||
|
||||
#include <QAtomicInt>
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QMutex>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QCoreApplication>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QProcess>
|
||||
#include <QQueue>
|
||||
#include <QThread>
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QAtomicInt>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
class QLocalSocket;
|
||||
|
||||
// Base class containing signals and slots - required because moc doesn't do
|
||||
// templated objects.
|
||||
|
||||
// Base class containing signals and slots - required because moc doesn't do templated objects.
|
||||
class _WorkerPoolBase : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
_WorkerPoolBase(QObject* parent = nullptr);
|
||||
_WorkerPoolBase(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
// Emitted when a worker failed to start. This usually happens when the
|
||||
// worker wasn't found, or couldn't be executed.
|
||||
// Emitted when a worker failed to start. This usually happens when the worker wasn't found, or couldn't be executed.
|
||||
void WorkerFailedToStart();
|
||||
|
||||
protected slots:
|
||||
@@ -54,45 +59,41 @@ protected slots:
|
||||
};
|
||||
|
||||
|
||||
// Manages a pool of one or more external processes. A local socket server is
|
||||
// started for each process, and the address is passed to the process as
|
||||
// argv[1]. The process is expected to connect back to the socket server, and
|
||||
// when it does a HandlerType is created for it.
|
||||
// Manages a pool of one or more external processes.
|
||||
// A local socket server is started for each process, and the address is passed to the process as argv[1].
|
||||
// The process is expected to connect back to the socket server, and when it does a HandlerType is created for it.
|
||||
// Instances of HandlerType are created in the WorkerPool's thread.
|
||||
template <typename HandlerType>
|
||||
class WorkerPool : public _WorkerPoolBase {
|
||||
public:
|
||||
WorkerPool(QObject* parent = nullptr);
|
||||
WorkerPool(QObject *parent = nullptr);
|
||||
~WorkerPool();
|
||||
|
||||
typedef typename HandlerType::MessageType MessageType;
|
||||
typedef typename HandlerType::ReplyType ReplyType;
|
||||
|
||||
// Sets the name of the worker executable. This is looked for first in the
|
||||
// current directory, and then in $PATH. You must call this before calling
|
||||
// Start().
|
||||
void SetExecutableName(const QString& executable_name);
|
||||
// Sets the name of the worker executable. This is looked for first in the current directory, and then in $PATH.
|
||||
// You must call this before calling Start().
|
||||
void SetExecutableName(const QString &executable_name);
|
||||
|
||||
// Sets the number of worker process to use. Defaults to
|
||||
// 1 <= (processors / 2) <= 2.
|
||||
// Sets the number of worker process to use. Defaults to 1 <= (processors / 2) <= 2.
|
||||
void SetWorkerCount(int count);
|
||||
|
||||
// Sets the prefix to use for the local server (on unix this is a named pipe
|
||||
// in /tmp). Defaults to QApplication::applicationName(). A random number
|
||||
// is appended to this name when creating each server.
|
||||
void SetLocalServerName(const QString& local_server_name);
|
||||
// Sets the prefix to use for the local server (on unix this is a named pipe in /tmp).
|
||||
// Defaults to QApplication::applicationName().
|
||||
// A random number is appended to this name when creating each server.
|
||||
void SetLocalServerName(const QString &local_server_name);
|
||||
|
||||
// Starts all workers.
|
||||
void Start();
|
||||
|
||||
// Fills in the message's "id" field and creates a reply future. The message
|
||||
// is queued and the WorkerPool's thread will send it to the next available
|
||||
// worker. Can be called from any thread.
|
||||
ReplyType* SendMessageWithReply(MessageType* message);
|
||||
// Fills in the message's "id" field and creates a reply future.
|
||||
// The message is queued and the WorkerPool's thread will send it to the next available worker.
|
||||
// Can be called from any thread.
|
||||
ReplyType *SendMessageWithReply(MessageType *message);
|
||||
|
||||
protected:
|
||||
// These are all reimplemented slots, they are called on the WorkerPool's
|
||||
// thread.
|
||||
// These are all reimplemented slots, they are called on the WorkerPool's thread.
|
||||
void DoStart();
|
||||
void NewConnection();
|
||||
void ProcessError(QProcess::ProcessError error);
|
||||
@@ -105,14 +106,14 @@ private:
|
||||
QLocalServer *local_server_;
|
||||
QLocalSocket *local_socket_;
|
||||
QProcess *process_;
|
||||
HandlerType* handler_;
|
||||
HandlerType *handler_;
|
||||
};
|
||||
|
||||
// Must only ever be called on my thread.
|
||||
void StartOneWorker(Worker* worker);
|
||||
void StartOneWorker(Worker *worker);
|
||||
|
||||
template <typename T>
|
||||
Worker* FindWorker(T Worker::*member, T value) {
|
||||
Worker *FindWorker(T Worker::*member, T value) {
|
||||
for (typename QList<Worker>::iterator it = workers_.begin() ;
|
||||
it != workers_.end() ; ++it) {
|
||||
if ((*it).*member == value) {
|
||||
@@ -123,7 +124,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DeleteQObjectPointerLater(T** p) {
|
||||
void DeleteQObjectPointerLater(T **p) {
|
||||
if (*p) {
|
||||
(*p)->deleteLater();
|
||||
*p = NULL;
|
||||
@@ -131,13 +132,11 @@ private:
|
||||
}
|
||||
|
||||
// Creates a new reply future for the request with the next sequential ID,
|
||||
// and sets the request's ID to the ID of the reply. Can be called from any
|
||||
// thread
|
||||
ReplyType* NewReply(MessageType* message);
|
||||
// and sets the request's ID to the ID of the reply. Can be called from any thread
|
||||
ReplyType *NewReply(MessageType *message);
|
||||
|
||||
// Returns the next handler, or NULL if there isn't one. Must be called from
|
||||
// my thread.
|
||||
HandlerType* NextHandler() const;
|
||||
// Returns the next handler, or NULL if there isn't one. Must be called from my thread.
|
||||
HandlerType *NextHandler() const;
|
||||
|
||||
private:
|
||||
QString local_server_name_;
|
||||
@@ -156,7 +155,7 @@ private:
|
||||
|
||||
|
||||
template <typename HandlerType>
|
||||
WorkerPool<HandlerType>::WorkerPool(QObject* parent)
|
||||
WorkerPool<HandlerType>::WorkerPool(QObject *parent)
|
||||
: _WorkerPoolBase(parent),
|
||||
next_worker_(0),
|
||||
next_id_(0)
|
||||
@@ -170,7 +169,7 @@ WorkerPool<HandlerType>::WorkerPool(QObject* parent)
|
||||
|
||||
template <typename HandlerType>
|
||||
WorkerPool<HandlerType>::~WorkerPool() {
|
||||
for (const Worker& worker : workers_) {
|
||||
for (const Worker &worker : workers_) {
|
||||
if (worker.local_socket_ && worker.process_) {
|
||||
disconnect(worker.process_, SIGNAL(error(QProcess::ProcessError)), this, SLOT(ProcessError(QProcess::ProcessError)));
|
||||
|
||||
@@ -190,7 +189,7 @@ WorkerPool<HandlerType>::~WorkerPool() {
|
||||
}
|
||||
}
|
||||
|
||||
for (ReplyType* reply : message_queue_) {
|
||||
for (ReplyType *reply : message_queue_) {
|
||||
reply->Abort();
|
||||
}
|
||||
}
|
||||
@@ -202,13 +201,13 @@ void WorkerPool<HandlerType>::SetWorkerCount(int count) {
|
||||
}
|
||||
|
||||
template <typename HandlerType>
|
||||
void WorkerPool<HandlerType>::SetLocalServerName(const QString& local_server_name) {
|
||||
void WorkerPool<HandlerType>::SetLocalServerName(const QString &local_server_name) {
|
||||
Q_ASSERT(workers_.isEmpty());
|
||||
local_server_name_ = local_server_name;
|
||||
}
|
||||
|
||||
template <typename HandlerType>
|
||||
void WorkerPool<HandlerType>::SetExecutableName(const QString& executable_name) {
|
||||
void WorkerPool<HandlerType>::SetExecutableName(const QString &executable_name) {
|
||||
Q_ASSERT(workers_.isEmpty());
|
||||
executable_name_ = executable_name;
|
||||
}
|
||||
@@ -233,7 +232,7 @@ void WorkerPool<HandlerType>::DoStart() {
|
||||
search_path << qApp->applicationDirPath() + "/../PlugIns";
|
||||
#endif
|
||||
|
||||
for (const QString& path_prefix : search_path) {
|
||||
for (const QString &path_prefix : search_path) {
|
||||
const QString executable_path = path_prefix + "/" + executable_name_;
|
||||
if (QFile::exists(executable_path)) {
|
||||
executable_path_ = executable_path;
|
||||
@@ -290,7 +289,7 @@ void WorkerPool<HandlerType>::NewConnection() {
|
||||
QLocalServer *server = qobject_cast<QLocalServer*>(sender());
|
||||
|
||||
// Find the worker with this server.
|
||||
Worker* worker = FindWorker(&Worker::local_server_, server);
|
||||
Worker *worker = FindWorker(&Worker::local_server_, server);
|
||||
if (!worker) return;
|
||||
|
||||
qLog(Debug) << "Worker" << worker << "connected to" << server->fullServerName();
|
||||
@@ -322,9 +321,8 @@ void WorkerPool<HandlerType>::ProcessError(QProcess::ProcessError error) {
|
||||
|
||||
switch (error) {
|
||||
case QProcess::FailedToStart:
|
||||
// Failed to start errors are bad - it usually means the worker isn't
|
||||
// installed. Don't restart the process, but tell our owner, who will
|
||||
// probably want to do something fatal.
|
||||
// Failed to start errors are bad - it usually means the worker isn't installed.
|
||||
// Don't restart the process, but tell our owner, who will probably want to do something fatal.
|
||||
qLog(Error) << "Worker failed to start";
|
||||
emit WorkerFailedToStart();
|
||||
break;
|
||||
@@ -339,7 +337,7 @@ void WorkerPool<HandlerType>::ProcessError(QProcess::ProcessError error) {
|
||||
|
||||
template <typename HandlerType>
|
||||
typename WorkerPool<HandlerType>::ReplyType*
|
||||
WorkerPool<HandlerType>::NewReply(MessageType* message) {
|
||||
WorkerPool<HandlerType>::NewReply(MessageType *message) {
|
||||
const int id = next_id_.fetchAndAddOrdered(1);
|
||||
message->set_id(id);
|
||||
|
||||
@@ -348,8 +346,8 @@ WorkerPool<HandlerType>::NewReply(MessageType* message) {
|
||||
|
||||
template <typename HandlerType>
|
||||
typename WorkerPool<HandlerType>::ReplyType*
|
||||
WorkerPool<HandlerType>::SendMessageWithReply(MessageType* message) {
|
||||
ReplyType* reply = NewReply(message);
|
||||
WorkerPool<HandlerType>::SendMessageWithReply(MessageType *message) {
|
||||
ReplyType *reply = NewReply(message);
|
||||
|
||||
// Add the pending reply to the queue
|
||||
{
|
||||
@@ -371,7 +369,7 @@ void WorkerPool<HandlerType>::SendQueuedMessages() {
|
||||
ReplyType *reply = message_queue_.dequeue();
|
||||
|
||||
// Find a worker for this message
|
||||
HandlerType* handler = NextHandler();
|
||||
HandlerType *handler = NextHandler();
|
||||
if (!handler) {
|
||||
// No available handlers - put the message on the front of the queue.
|
||||
message_queue_.prepend(reply);
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "fmpsparser.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QtDebug>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "fmpsparser.h"
|
||||
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
@@ -114,8 +117,7 @@ int FMPSParser::ParseListListRef(const QStringRef &data, Result *ret) const {
|
||||
return ParseContainer<';'>(data, std::bind(&FMPSParser::ParseListRef, this, _1, _2), ret);
|
||||
}
|
||||
|
||||
// Convenience functions that take QStrings instead of QStringRefs. Use the
|
||||
// QStringRef versions if possible, they're faster.
|
||||
// Convenience functions that take QStrings instead of QStringRefs. Use the QStringRef versions if possible, they're faster.
|
||||
int FMPSParser::ParseValue(const QString &data, QVariant *ret) const {
|
||||
return ParseValueRef(QStringRef(&data), ret);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,13 @@
|
||||
#ifndef FMPSPARSER_H
|
||||
#define FMPSPARSER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QVariantList>
|
||||
|
||||
class FMPSParser {
|
||||
public:
|
||||
@@ -30,7 +35,7 @@ public:
|
||||
typedef QList<QVariantList> Result;
|
||||
|
||||
// Parses a FMPS value and returns true on success.
|
||||
bool Parse(const QString& data);
|
||||
bool Parse(const QString &data);
|
||||
|
||||
// Gets the result of the last successful Parse.
|
||||
Result result() const { return result_; }
|
||||
|
||||
@@ -15,50 +15,75 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tagreader.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTextCodec>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
#include <aifffile.h>
|
||||
#include <asffile.h>
|
||||
#include <attachedpictureframe.h>
|
||||
#include <commentsframe.h>
|
||||
#include <fileref.h>
|
||||
#include <audioproperties.h>
|
||||
#include <flacfile.h>
|
||||
#include <flacproperties.h>
|
||||
#include <id3v2tag.h>
|
||||
#include <mp4file.h>
|
||||
#include <mp4tag.h>
|
||||
#include <mpcfile.h>
|
||||
#include <mpegfile.h>
|
||||
#include <oggfile.h>
|
||||
#ifdef TAGLIB_HAS_OPUS
|
||||
#include <opusfile.h>
|
||||
#endif
|
||||
#include <oggflacfile.h>
|
||||
#include <popularimeterframe.h>
|
||||
#include <speexfile.h>
|
||||
#include <tag.h>
|
||||
#include <textidentificationframe.h>
|
||||
#include <trueaudiofile.h>
|
||||
#include <tstring.h>
|
||||
#include <vorbisfile.h>
|
||||
#include <wavfile.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "fmpsparser.h"
|
||||
#include <taglib/taglib.h>
|
||||
#include <taglib/taglib_config.h>
|
||||
#include <taglib/fileref.h>
|
||||
#include <taglib/tbytevector.h>
|
||||
#include <taglib/tfile.h>
|
||||
#include <taglib/tlist.h>
|
||||
#include <taglib/tstring.h>
|
||||
#include <taglib/tstringlist.h>
|
||||
#include <taglib/audioproperties.h>
|
||||
#include <taglib/trueaudiofile.h>
|
||||
#include <taglib/attachedpictureframe.h>
|
||||
#include <taglib/textidentificationframe.h>
|
||||
#include <taglib/xiphcomment.h>
|
||||
#include <taglib/commentsframe.h>
|
||||
#include <taglib/tag.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
#include "taglib/id3v2frame.h"
|
||||
#include <taglib/flacfile.h>
|
||||
#include <taglib/oggflacfile.h>
|
||||
#include <taglib/flacproperties.h>
|
||||
#include <taglib/flacpicture.h>
|
||||
#include <taglib/vorbisfile.h>
|
||||
#include <taglib/speexfile.h>
|
||||
#include <taglib/wavfile.h>
|
||||
#include <taglib/aifffile.h>
|
||||
#include <taglib/asffile.h>
|
||||
#include "taglib/asftag.h"
|
||||
#include "taglib/asfattribute.h"
|
||||
#include "taglib/asfproperties.h"
|
||||
#include <taglib/mp4file.h>
|
||||
#include <taglib/mp4tag.h>
|
||||
#include "taglib/mp4item.h"
|
||||
#include <taglib/mp4coverart.h>
|
||||
#include <taglib/mp4properties.h>
|
||||
#include <taglib/mpcfile.h>
|
||||
#include <taglib/mpegfile.h>
|
||||
|
||||
#ifdef TAGLIB_HAS_OPUS
|
||||
#include <taglib/opusfile.h>
|
||||
#endif
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QList>
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QTextCodec>
|
||||
#include <QVector>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/messagehandler.h"
|
||||
|
||||
#include "fmpsparser.h"
|
||||
#include "core/timeconstants.h"
|
||||
|
||||
// Taglib added support for FLAC pictures in 1.7.0
|
||||
@@ -71,12 +96,12 @@
|
||||
class FileRefFactory {
|
||||
public:
|
||||
virtual ~FileRefFactory() {}
|
||||
virtual TagLib::FileRef *GetFileRef(const QString& filename) = 0;
|
||||
virtual TagLib::FileRef *GetFileRef(const QString &filename) = 0;
|
||||
};
|
||||
|
||||
class TagLibFileRefFactory : public FileRefFactory {
|
||||
public:
|
||||
virtual TagLib::FileRef *GetFileRef(const QString& filename) {
|
||||
virtual TagLib::FileRef *GetFileRef(const QString &filename) {
|
||||
#ifdef Q_OS_WIN32
|
||||
return new TagLib::FileRef(filename.toStdWString().c_str());
|
||||
#else
|
||||
@@ -87,11 +112,11 @@ class TagLibFileRefFactory : public FileRefFactory {
|
||||
|
||||
namespace {
|
||||
|
||||
TagLib::String StdStringToTaglibString(const std::string& s) {
|
||||
TagLib::String StdStringToTaglibString(const std::string &s) {
|
||||
return TagLib::String(s.c_str(), TagLib::String::UTF8);
|
||||
}
|
||||
|
||||
TagLib::String QStringToTaglibString(const QString& s) {
|
||||
TagLib::String QStringToTaglibString(const QString &s) {
|
||||
return TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8);
|
||||
}
|
||||
|
||||
@@ -508,8 +533,7 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
||||
}
|
||||
|
||||
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
||||
// apart, so we keep specific behavior for some formats by adding another
|
||||
// "else if" block above.
|
||||
// apart, so we keep specific behavior for some formats by adding another "else if" block above.
|
||||
if (TagLib::Ogg::XiphComment *tag = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
||||
SetVorbisComments(tag, song);
|
||||
}
|
||||
@@ -625,9 +649,7 @@ QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap();
|
||||
|
||||
#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11
|
||||
// Other than the below mentioned non-standard COVERART,
|
||||
// METADATA_BLOCK_PICTURE
|
||||
// is the proposed tag for cover pictures.
|
||||
// Other than the below mentioned non-standard COVERART, METADATA_BLOCK_PICTURE is the proposed tag for cover pictures.
|
||||
// (see http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE)
|
||||
if (map.contains("METADATA_BLOCK_PICTURE")) {
|
||||
TagLib::StringList pict_list = map["METADATA_BLOCK_PICTURE"];
|
||||
@@ -687,10 +709,10 @@ QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(ref.file());
|
||||
if (aac_file) {
|
||||
TagLib::MP4::Tag *tag = aac_file->tag();
|
||||
const TagLib::MP4::ItemListMap& items = tag->itemListMap();
|
||||
const TagLib::MP4::ItemListMap &items = tag->itemListMap();
|
||||
TagLib::MP4::ItemListMap::ConstIterator it = items.find("covr");
|
||||
if (it != items.end()) {
|
||||
const TagLib::MP4::CoverArtList& art_list = it->second.toCoverArtList();
|
||||
const TagLib::MP4::CoverArtList &art_list = it->second.toCoverArtList();
|
||||
|
||||
if (!art_list.isEmpty()) {
|
||||
// Just take the first one for now
|
||||
|
||||
@@ -18,18 +18,19 @@
|
||||
#ifndef TAGREADER_H
|
||||
#define TAGREADER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include <taglib/xiphcomment.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QString;
|
||||
class QTextCodec;
|
||||
class QUrl;
|
||||
|
||||
namespace TagLib {
|
||||
class FileRef;
|
||||
class String;
|
||||
@@ -44,15 +45,14 @@ class FileRefFactory;
|
||||
|
||||
/**
|
||||
* This class holds all useful methods to read and write tags from/to files.
|
||||
* You should not use it directly in the main process but rather use a
|
||||
* TagReaderWorker process (using TagReaderClient)
|
||||
* You should not use it directly in the main process but rather use a TagReaderWorker process (using TagReaderClient)
|
||||
*/
|
||||
class TagReader {
|
||||
public:
|
||||
TagReader();
|
||||
|
||||
void ReadFile(const QString& filename, pb::tagreader::SongMetadata *song) const;
|
||||
bool SaveFile(const QString& filename, const pb::tagreader::SongMetadata &song) const;
|
||||
void ReadFile(const QString &filename, pb::tagreader::SongMetadata *song) const;
|
||||
bool SaveFile(const QString &filename, const pb::tagreader::SongMetadata &song) const;
|
||||
|
||||
bool IsMediaFile(const QString &filename) const;
|
||||
QByteArray LoadEmbeddedArt(const QString &filename) const;
|
||||
|
||||
@@ -15,16 +15,23 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tagreaderworker.h"
|
||||
#include "core/logging.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QLocalSocket>
|
||||
#include <QSsl>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslSocket>
|
||||
#include <QStringList>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/time.h>
|
||||
#include "core/logging.h"
|
||||
#include "tagreaderworker.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tagreaderworker.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QTextCodec>
|
||||
#include <QUrl>
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "tagreaderworker.h"
|
||||
|
||||
TagReaderWorker::TagReaderWorker(QIODevice *socket, QObject *parent)
|
||||
: AbstractMessageHandler<pb::tagreader::Message>(socket, parent)
|
||||
|
||||
@@ -19,9 +19,15 @@
|
||||
#define TAGREADERWORKER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
|
||||
#include "core/messagehandler.h"
|
||||
#include "tagreader.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
#include "core/messagehandler.h"
|
||||
|
||||
class TagReaderWorker : public AbstractMessageHandler<pb::tagreader::Message> {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user