virtual Command rawCommand() const;
+ /**
+ If it's false the client takes ownership of the request!
+ **/
virtual bool waitForResult() const;
virtual bool requiresSession() const;
};
+#define REPLY_DEFINITION_HELPER_INTERNAL(name, constructor) \
+friend class Client; \
+public: \
+typedef name##Command CommandType; \
+private: \
+CommandType m_command; \
+Client *m_client; \
+name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {constructor} \
+inline const CommandType &command() const { return m_command; }
+
#define REPLY_DEFINITION_HELPER(name) \
- friend class Client; \
- public: \
- typedef name##Command CommandType; \
- private: \
- CommandType m_command; \
- Client *m_client; \
- name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {m_commandPtr = &m_command;} \
- inline const CommandType &command() const { return m_command; }
+ REPLY_DEFINITION_HELPER_INTERNAL(name, m_commandPtr = &m_command;)
#define REPLY_DEFINITION_HELPER2(name) \
- friend class Client; \
- public: \
- typedef name##Command CommandType; \
- private: \
- CommandType m_command; \
- Client *m_client; \
- name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {m_commandPtr = &m_command; init();} \
- inline const CommandType &command() const { return m_command; }
+ REPLY_DEFINITION_HELPER_INTERNAL(name, m_commandPtr = &m_command; init();)
class ANIDBUDPCLIENTSHARED_EXPORT AbstractReply : public QObject
{
qDebug() << "Api instance init!";
authReply = 0;
+ uptimeReply = 0;
m_error = NoError;
m_idlePolicy = DoNothingIdlePolicy;
Client::~Client()
{
- disconnect();
- clearCommandQueue();
-
foreach (CommandData *cmd, sentCommands)
{
- if (!cmd->command->command().waitForResult())
- {
- // Send CLIENT_DESTROYED to indicate that no real reply will come.
- cmd->command->setRawReply(CLIENT_DESTROYED, "");
- }
+ // Send CLIENT_DESTROYED to indicate that no real reply will come.
+ cmd->command->setRawReply(CLIENT_DESTROYED, "");
}
+ sentCommands.clear();
+
+ clearCommandQueue();
if (!m_sessionId.isEmpty())
{
while (commandTimer->isActive())
QCoreApplication::processEvents();
- sendCommand(createReply(LogoutCommand()), true);
+ logout(true);
socket->waitForBytesWritten(5);
}
+ disconnect();
+ if (authReply)
+ {
+ delete authReply;
+ authReply = 0;
+ }
+ if (uptimeReply)
+ {
+ delete uptimeReply;
+ uptimeReply = 0;
+ }
}
QString Client::host() const
idleTimer->start(UDP_API_INACTIVITY_UPDATE * 1000);
break;
case ImmediateLogoutIdlePolicy:
- enqueueControlCommand(logoutReply);
+ logout(true);
break;
default:
break;
case LOGIN_FIRST:
case INVALID_SESSION:
qDebug() << "LOGIN FIRST required, authing";
- m_sessionId = "";
+ m_sessionId.clear();
if (controlCommand)
enqueueControlCommand(cmd);
else
goto continueLoop;
break;
case LOGGED_OUT:
- m_sessionId = "";
+ m_sessionId.clear();
break;
case BANNED:
m_error = BannedError;
reply = reply.mid(10);
cmd->setRawReply(replyCode, reply);
+
+ // Delete if command is owned by the client.
+ if (!cmd->command().waitForResult())
+ delete cmd;
continueLoop:
;
}
AbstractReply *reply = commandQueue.dequeue();
if (!reply->command().waitForResult())
{
- // These would be deleted anyway
+ // These are owned by the client
delete reply;
}
else
AbstractReply *reply = commandQueue.dequeue();
if (!reply->command().waitForResult())
{
- // These would be deleted anyway
+ // These are owned by the client
delete reply;
}
else
void Client::logout()
{
- if (!m_sessionId.isEmpty())
- enqueueControlCommand(logoutReply);
+ logout(false);
+}
+
+void Client::logout(bool force)
+{
+ if (m_sessionId.isEmpty())
+ return;
+ enqueueControlCommand(createReply(LogoutCommand()), force);
}
void Client::commandTimeout(const QByteArray &commandId)
File::~File()
{
+ if (markReply)
+ {
+ delete markReply;
+ markReply = 0;
+ }
if (fileReply)
{
delete fileReply;
return true;
}
-bool File::markWatched(bool watched)
+bool File::markWatched()
{
- if (m_markingState != Success)
+ if (m_markingState == Success)
return true;
if (m_hashingState != Success)
actionsQueue.enqueue(Hashing);
+ if (m_addingState != Success)
+ actionsQueue.enqueue(Adding);
+
+ actionsQueue.enqueue(MarkingWatched);
+
if (notWorking) work();
- return watched;
+ return true;
}
void File::finishMarking(bool success)
{
- Q_UNUSED(success);
+ if (!success)
+ {
+ updateStatus(MarkingWatched, Failure);
+ return;
+ }
+ updateStatus(MarkingWatched, Success);
}
void File::work()
if (actionsQueue.isEmpty())
{
emit statusUpdate(All, Finished);
+ emit finished();
notWorking = true;
return;
}
work();
return;
}
+ MyListAddCommand markCommand(0);
+ if (addReply->lid())
+ markCommand = MyListAddCommand(addReply->lid());
+ else
+ markCommand = MyListAddCommand(m_ed2k, size(), true);
+ markCommand.setViewed(true);
+
+ if (markReply) markReply->deleteLater();
+ markReply = Client::instance()->send(markCommand);
+ connect(markReply, SIGNAL(replyReady(bool)), this, SLOT(finishMarking(bool)));
+
+ updateStatus(MarkingWatched, InProgress);
}
void File::init()
hashResult = 0;
fileReply = 0;
addReply = 0;
+ markReply = 0;
m_hashingState = m_renamingState = m_addingState = m_markingState = NotStarted;
notWorking = true;
#ifndef NO_ANIDBUDPCLIENT
# include <AniDBUdpClient/Client>
-# include <AniDBUdpClient/RawCommand>
-# include <AniDBUdpClient/MyListAddCommand>
-# include <AniDBUdpClient/Hash>
#endif
#include <QDebug>
destroyed = menuMoving = windowMoving = m_closeOnStop = false;
#ifndef NO_ANIDBUDPCLIENT
- anidb = AniDBUdpClient::Client::instance();
- addReply = 0;
m_marked = true;
m_automark = 0;
#endif
#endif
#ifndef NO_ANIDBUDPCLIENT
- anidb->setCompression(true);
- anidb->setIdlePolicy(AniDBUdpClient::ImmediateLogoutIdlePolicy);
+ AniDBUdpClient::Client::instance()->setCompression(true);
+ AniDBUdpClient::Client::instance()->setIdlePolicy(AniDBUdpClient::ImmediateLogoutIdlePolicy);
#endif
}
hide();
menu->hide();
-
- anidb = 0;
}
QString VideoWindow::currentFile() const
#ifndef NO_ANIDBUDPCLIENT
void VideoWindow::markWatched()
{
- if (addReply != 0)
+ if (m_marked)
{
- menu->showMessage("File already Marked");
+ menu->showMessage(tr("File already marked"));
return;
}
- menu->showMessage("Hashing file");
- AniDBUdpClient::HashRequest hashRequest(videoPlayer->currentFile());
-
- AniDBUdpClient::HashResult *hashResult = AniDBUdpClient::Hash::instance()->hashFile(hashRequest);
- qDebug() << "hashing file...";
- connect(hashResult, SIGNAL(resultReady()), this, SLOT(doMarkWatched()));
-}
-
-void VideoWindow::doMarkWatched()
-{
- AniDBUdpClient::HashResult *hashResult = qobject_cast<AniDBUdpClient::HashResult *>(sender());
- if (!hashResult)
- return;
- AniDBUdpClient::MyListAddCommand addCommand(hashResult->hash(), QFileInfo(videoPlayer->currentFile()).size(), false);
- AniDBUdpClient::MyListAddReply *addReply = anidb->send(addCommand);
- connect(addReply, SIGNAL(replyReady(bool)), this, SLOT(showMarkResult(bool)));
- connect(addReply, SIGNAL(replyReady(bool)), this, SLOT(deleteLater()));
+ menu->showMessage(tr("Starting marking file as watched."));
- menu->showMessage(tr("Marking file %1").arg(hashResult->fileInfo().fileName()));
- hashResult->deleteLater();
+ AniDBUdpClient::File *file = new AniDBUdpClient::File(videoPlayer->currentFile());
+ file->markWatched();
+ connect(file, SIGNAL(statusUpdate(AniDBUdpClient::File::Action,AniDBUdpClient::File::ActionState)), this, SLOT(markingStatus(AniDBUdpClient::File::Action,AniDBUdpClient::File::ActionState)));
+ connect(file, SIGNAL(finished()), file, SLOT(deleteLater()));
}
-void VideoWindow::showMarkResult(bool success)
+void VideoWindow::markingStatus(AniDBUdpClient::File::Action action, AniDBUdpClient::File::ActionState actionState)
{
- AniDBUdpClient::MyListAddReply *cmd = qobject_cast<AniDBUdpClient::MyListAddReply *>(sender());
- if (!cmd)
- return;
-
- if (success)
- {
- menu->showMessage(tr("File marked watched"));
- }
- else
+ AniDBUdpClient::File *file = (AniDBUdpClient::File *) sender();
+ switch (action)
{
- menu->showMessage(tr("Failed to mark file"));
+ case AniDBUdpClient::File::Hashing:
+ switch (actionState)
+ {
+ case AniDBUdpClient::File::InProgress:
+ menu->showMessage(tr("Hashing File"));
+ break;
+ default: ;
+ }
+ break;
+ case AniDBUdpClient::File::MarkingWatched:
+ switch (actionState)
+ {
+ case AniDBUdpClient::File::InProgress:
+ menu->showMessage(tr("Marking File"));
+ break;
+ case AniDBUdpClient::File::Success:
+ menu->showMessage(tr("File %1 marked watched").arg(file->file().fileName()));
+ break;
+ case AniDBUdpClient::File::Failure:
+ menu->showMessage(tr("Failed to mark file %1 as watched").arg(file->file().fileName()));
+ break;
+ default: ;
+ }
+ break;
+ default: ;
}
- cmd->deleteLater();
}
void VideoWindow::anidbSettings()
{
AniDBConfigDialog dialog(this);
- dialog.setHost(anidb->host());
- dialog.setHostPort(anidb->hostPort());
- dialog.setLocalPort(anidb->localPort());
- dialog.setUser(anidb->user());
- dialog.setPass(anidb->pass());
+ dialog.setHost(AniDBUdpClient::Client::instance()->host());
+ dialog.setHostPort(AniDBUdpClient::Client::instance()->hostPort());
+ dialog.setLocalPort(AniDBUdpClient::Client::instance()->localPort());
+ dialog.setUser(AniDBUdpClient::Client::instance()->user());
+ dialog.setPass(AniDBUdpClient::Client::instance()->pass());
dialog.setAutomark(m_automark);
dialog.setPaths(m_automarkPaths);
return;
}
- anidb->disconnect();
+ AniDBUdpClient::Client::instance()->disconnect();
- anidb->setHost(dialog.host());
- anidb->setHostPort(dialog.hostPort());
- anidb->setLocalPort(dialog.localPort());
- anidb->setUser(dialog.user());
- anidb->setPass(dialog.pass());
+ AniDBUdpClient::Client::instance()->setHost(dialog.host());
+ AniDBUdpClient::Client::instance()->setHostPort(dialog.hostPort());
+ AniDBUdpClient::Client::instance()->setLocalPort(dialog.localPort());
+ AniDBUdpClient::Client::instance()->setUser(dialog.user());
+ AniDBUdpClient::Client::instance()->setPass(dialog.pass());
m_automark = dialog.automark();
m_automarkPaths = dialog.paths();
settings.endGroup();
# ifndef NO_ANIDBUDPCLIENT
settings.beginGroup("anidbudpapiclient");
- settings.setValue("host", anidb->host());
- settings.setValue("hostPort", anidb->hostPort());
- settings.setValue("localPort", anidb->localPort());
- settings.setValue("user", anidb->user());
- settings.setValue("pass", anidb->pass());
+ settings.setValue("host", AniDBUdpClient::Client::instance()->host());
+ settings.setValue("hostPort", AniDBUdpClient::Client::instance()->hostPort());
+ settings.setValue("localPort", AniDBUdpClient::Client::instance()->localPort());
+ settings.setValue("user", AniDBUdpClient::Client::instance()->user());
+ settings.setValue("pass", AniDBUdpClient::Client::instance()->pass());
settings.setValue("automark", m_automark);
settings.setValue("paths", m_automarkPaths);
settings.endGroup();
settings.endGroup();
# ifndef NO_ANIDBUDPCLIENT
settings.beginGroup("anidbudpapiclient");
- anidb->setHost(settings.value("host", "api.anidb.info").toString());
- anidb->setHostPort(settings.value("hostPort", 9000).toInt());
- anidb->setLocalPort(settings.value("localPort", 9001).toInt());
- anidb->setUser(settings.value("user").toString());
- anidb->setPass(settings.value("pass").toString());
+ AniDBUdpClient::Client::instance()->setHost(settings.value("host", "api.anidb.info").toString());
+ AniDBUdpClient::Client::instance()->setHostPort(settings.value("hostPort", 9000).toInt());
+ AniDBUdpClient::Client::instance()->setLocalPort(settings.value("localPort", 9001).toInt());
+ AniDBUdpClient::Client::instance()->setUser(settings.value("user").toString());
+ AniDBUdpClient::Client::instance()->setPass(settings.value("pass").toString());
m_automark = settings.value("automark", 0).toInt();
m_automarkPaths = settings.value("paths", QStringList()).toStringList();
settings.endGroup();