server.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include <QtGui>
  2. #include <QtNetwork>
  3. #include <QDebug>
  4. #include <QProcess>
  5. #include <stdlib.h>
  6. #include <QXmlQuery>
  7. #include "server.h"
  8. const QString KXmlFileName = "xmlfilename";
  9. const QString KId = "id";
  10. const QString KSource = "source";
  11. const QString KPlayer = "player";
  12. const QString KXqReadCommandForPlayer = "let $root:=doc($xmlfilename)//commands where $root/@player=$player return data($root/@command)";
  13. const QString KXqReadOption = "let $root:=doc($xmlfilename)//commands for $operation in $root/operation where $operation/@id=$id return data($operation/option)";
  14. const QString KLinuxCommandFileName = "linux_commands.xml";
  15. const QString KWindowsCommandFileName = "win_commands.xml";
  16. const QString KRhythmbox = "rhythmbox";
  17. const QString KWinamp = "winamp";
  18. const QString KNowPlaying = "nowplaying";
  19. const QString KPlay = "play";
  20. const QString KSyncNow = "syncnow";
  21. const QString KConnect = "connect";
  22. const QString KResponseTemplate = "<response><status>%1</status><request>%2</request><text>%3</text></response>";
  23. const int KStatusSuccess = 200;
  24. const int KStatusInternalError = 500;
  25. const int KOneSecondInMs = 1000;
  26. Server::Server(QWidget *parent)
  27. : QDialog(parent), tcpServer(0), networkSession(0),
  28. mInternalSync(false)
  29. {
  30. statusLabel = new QLabel;
  31. quitButton = new QPushButton(tr("Quit"));
  32. quitButton->setAutoDefault(false);
  33. mCurrentTrackName.clear();
  34. mProcess = new QProcess(this);
  35. mXmlQuery = new QXmlQuery;
  36. mCurrentRequest.clear();
  37. connect(mProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(processFinished(int,QProcess::ExitStatus)));
  38. // Populate command filename depending on the underlying platform
  39. QString commandsFileName;
  40. #ifdef Q_OS_LINUX
  41. commandsFileName = ":/xml/linux_commands.xml";
  42. // TODO: Add support to get the player name dynamically
  43. mPlayerName = KRhythmbox;
  44. #else Q_OS_WIN32
  45. commandsFileName = ":/xml/win_commands.xml";
  46. mPlayerName = KWinamp;
  47. #endif
  48. mCommands = new QFile(commandsFileName,this);
  49. if(!mCommands->open(QIODevice::ReadOnly))
  50. {
  51. }
  52. openSession();
  53. connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
  54. connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
  55. QHBoxLayout *buttonLayout = new QHBoxLayout;
  56. buttonLayout->addStretch(1);
  57. buttonLayout->addWidget(quitButton);
  58. buttonLayout->addStretch(1);
  59. QVBoxLayout *mainLayout = new QVBoxLayout;
  60. mainLayout->addWidget(statusLabel);
  61. mainLayout->addLayout(buttonLayout);
  62. setLayout(mainLayout);
  63. setWindowTitle(tr("Angel Server"));
  64. }
  65. Server::~Server()
  66. {
  67. delete mXmlQuery;
  68. }
  69. void Server::openSession()
  70. {
  71. tcpServer = new QTcpServer(this);
  72. if (!tcpServer->listen(QHostAddress::Any,1500)) {
  73. QMessageBox::critical(this, tr("Angel Server"),
  74. tr("Unable to start the server: %1.")
  75. .arg(tcpServer->errorString()));
  76. close();
  77. return;
  78. }
  79. QString ipAddress;
  80. QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
  81. // use the first non-localhost IPv4 address
  82. for (int i = 0; i < ipAddressesList.size(); ++i) {
  83. if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
  84. ipAddressesList.at(i).toIPv4Address()) {
  85. ipAddress = ipAddressesList.at(i).toString();
  86. break;
  87. }
  88. }
  89. // if we did not find one, use IPv4 localhost
  90. if (ipAddress.isEmpty())
  91. ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
  92. statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n"
  93. "Run the Angel Client now. \n"
  94. "In case of connection error, manually set IP and port and click connect in Angel Client")
  95. .arg(ipAddress).arg(tcpServer->serverPort()));
  96. }
  97. void Server::handleNewConnection()
  98. {
  99. mCommandForPlayer = commandForPlayer(mPlayerName);
  100. QByteArray response = "Conneted Successfully : "+mPlayerName.toLocal8Bit();
  101. if(mCommandForPlayer.isEmpty())
  102. {
  103. response = "No supporting player!";
  104. }
  105. mClientConnection = tcpServer->nextPendingConnection();
  106. connect(mClientConnection, SIGNAL(disconnected()),
  107. mClientConnection, SLOT(deleteLater()));
  108. connect(mClientConnection,SIGNAL(readyRead()),this,SLOT(handleRequest()));
  109. sendResponse(KStatusSuccess,response);
  110. // start sync timer
  111. startTimer(KOneSecondInMs*4);
  112. }
  113. void Server::handleRequest()
  114. {
  115. mCurrentRequest = mClientConnection->readAll().simplified();
  116. qDebug()<<"requestFromClient: "<<mCurrentRequest;
  117. executeCommand(mCurrentRequest);
  118. }
  119. void Server::executeCommand(QString aRequest)
  120. {
  121. QString opt = option(aRequest);
  122. QString commandToExecute = mCommandForPlayer+opt;
  123. commandToExecute = commandToExecute.simplified();
  124. qDebug()<<"commandToExecute:"<<commandToExecute;
  125. mProcess->start(commandToExecute);
  126. }
  127. void Server::processFinished (int exitCode,QProcess::ExitStatus exitStatus)
  128. {
  129. qDebug()<<__FUNCTION__;
  130. QString response = mProcess->readAllStandardOutput().simplified();
  131. // check if sycn is required
  132. if(mInternalSync)
  133. {
  134. mInternalSync = false;
  135. qDebug()<<"sync required: "<<mCurrentTrackName<<" "<<response;
  136. if(mCurrentTrackName != response)
  137. {
  138. mCurrentTrackName = response;
  139. sync();
  140. }
  141. }
  142. else
  143. {
  144. int stat = (0 == exitCode)?(KStatusSuccess):(KStatusInternalError);
  145. sendResponse(stat,response);
  146. }
  147. }
  148. void Server::readProcessOutput()
  149. {
  150. qDebug()<<__FUNCTION__;
  151. qDebug()<<mProcess->exitStatus();
  152. qDebug()<<mProcess->exitCode();
  153. }
  154. void Server::timerEvent(QTimerEvent *event)
  155. {
  156. checkIsSyncRequired();
  157. }
  158. void Server::checkIsSyncRequired()
  159. {
  160. mInternalSync = true;
  161. executeCommand(KNowPlaying); // check for track title
  162. }
  163. void Server::sync()
  164. {
  165. sendResponse(KStatusSuccess,KSyncNow);
  166. }
  167. QString Server::commandForPlayer(QString aPlayerName)
  168. {
  169. mCommands->reset();
  170. QXmlQuery* xmlQuery = new QXmlQuery;
  171. xmlQuery->bindVariable(KXmlFileName,mCommands);
  172. xmlQuery->bindVariable(KPlayer,QVariant(aPlayerName));
  173. xmlQuery->setQuery(KXqReadCommandForPlayer);
  174. QString result = QString();
  175. if(xmlQuery->isValid())
  176. {
  177. xmlQuery->evaluateTo(&result);
  178. }
  179. delete xmlQuery;
  180. return result;
  181. }
  182. QString Server::option(QString aId)
  183. {
  184. mCommands->reset();
  185. mXmlQuery->bindVariable(KXmlFileName,mCommands);
  186. mXmlQuery->bindVariable(KId,QVariant(aId));
  187. mXmlQuery->setQuery(KXqReadOption);
  188. QString result = QString();
  189. if(mXmlQuery->isValid())
  190. {
  191. mXmlQuery->evaluateTo(&result);
  192. }
  193. qDebug()<<result;
  194. return result;
  195. }
  196. void Server::sendResponse(int aStatus, QString aResponseText)
  197. {
  198. qDebug()<<__FUNCTION__;
  199. QString resp = KResponseTemplate.arg(aStatus).arg(mCurrentRequest).arg(aResponseText);
  200. qDebug()<<resp;
  201. mClientConnection->write(resp.toUtf8());
  202. }
  203. //eof