diff options
| -rw-r--r-- | src/guard.cpp | 125 | ||||
| -rw-r--r-- | src/guard.h | 36 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 15 | ||||
| -rw-r--r-- | src/qmmpstarter.cpp | 100 | ||||
| -rw-r--r-- | src/qmmpstarter.h | 16 | ||||
| -rw-r--r-- | src/src.pro | 10 | ||||
| -rw-r--r-- | src/tcpserver.cpp | 69 | ||||
| -rw-r--r-- | src/tcpserver.h | 51 | ||||
| -rw-r--r-- | src/unixdomainsocket.cpp | 67 | ||||
| -rw-r--r-- | src/unixdomainsocket.h | 46 | ||||
| -rw-r--r-- | src/version.h | 7 |
11 files changed, 188 insertions, 354 deletions
diff --git a/src/guard.cpp b/src/guard.cpp deleted file mode 100644 index d9c701951..000000000 --- a/src/guard.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "guard.h" - -//#define USE_SEMAPHORE - -#ifdef USE_SEMAPHORE - #include <sys/types.h> - #include <sys/ipc.h> - #include <errno.h> - #include <sys/sem.h> -#else - #include <QSettings> -#endif - -#include <QDir> - -bool Guard::create(const QString& filepath) -{ -#ifdef USE_SEMAPHORE - key_t key; - int sem_num = 1; - if( (key = ftok(filepath.toAscii().data(),'A')) < 0) - { - qWarning("Warning: Unable get access to key..."); - return false; - } - - if(semget(key,sem_num,IPC_CREAT | IPC_EXCL ) < 0) - { - if(errno == EEXIST) - { - qWarning("Warning: Semaphore with %d key already exists...",key); - } - return false; - } - - return true; -#else - Q_UNUSED(filepath) - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("Application"); - settings.setValue("IS_RUNNING",TRUE); - settings.endGroup(); - return true; -#endif -} - -bool Guard::exists(const QString& filepath) -{ -#ifdef USE_SEMAPHORE - key_t key; - int sem_num = 1; - int sem_id; - - if( (key = ftok(filepath.toAscii().data(),'A')) < 0) - { - qWarning("Warning: Unable get access to key"); - return false; - } - - if( (sem_id = semget(key,sem_num,0)) < 0 ) - return false; - return true; -#else - Q_UNUSED(filepath) - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("Application"); - bool res = settings.value("IS_RUNNING",FALSE).toBool(); - settings.endGroup(); - return res; -#endif -} - -bool Guard::destroy(const QString& filepath) -{ -#ifdef USE_SEMAPHORE - key_t key; - int sem_num = 1; - int sem_id; - - if( (key = ftok(filepath.toAscii().data(),'A')) < 0) - { - qWarning("Warning: Unable get access to key"); - return false; - } - if( (sem_id = semget(key,sem_num,0)) < 0 ) - { - qWarning("Unable get semaphore with key %d",key); - return false; - } - - if(semctl(sem_id,1,IPC_RMID) < 0) - { - qWarning("Unable remove semaphore with key %d",key); - return false; - } - return true; -#else - Q_UNUSED(filepath) - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("Application"); - settings.setValue("IS_RUNNING",FALSE); - settings.endGroup(); - return true; -#endif -} diff --git a/src/guard.h b/src/guard.h deleted file mode 100644 index 2ae05be4a..000000000 --- a/src/guard.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef _GUARD_H -#define _GUARD_H - -#include <QString> - -/** - @author Vladimir Kuznetsov <vovanec@gmail.com> - */ -struct Guard -{ - static bool create(const QString& filepath); - static bool exists(const QString& filepath); - static bool destroy(const QString& filepath); -}; -#endif - diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 36d672175..1e8280875 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -39,7 +39,6 @@ #include "eqwidget.h" #include "mainvisual.h" #include "playlistformat.h" -#include "tcpserver.h" #include "jumptotrackdialog.h" #include "aboutdialog.h" #include <addurldialog.h> @@ -138,10 +137,6 @@ MainWindow::MainWindow(const QStringList& args, QWidget *parent) updateEQ(); updateSkin(); - // Starting the TcpServer - - new TcpServer(this); - FileDialog::registerBuiltinFactories(); FileDialog::registerExternalFactories(); @@ -764,9 +759,17 @@ bool MainWindow::processCommandArgs(const QStringList &slist,const QString& cwd) else if (str == "--pause") pause(); else if (str == "--next") + { next(); + if(!m_core->isInitialized()) + play(); + } else if (str == "--previous") + { previous(); + if(!m_core->isInitialized()) + play(); + } else if (str == "--play-pause") playPause(); else @@ -781,8 +784,6 @@ bool MainWindow::processCommandArgs(const QStringList &slist,const QString& cwd) full_path_list << s; else full_path_list << cwd + "/" + s; - //qWarning("Current working dir: %s",qPrintable(workingDir)); - //qWarning("Full path to play: %s",qPrintable(workingDir + "/" + s)); } setFileList(full_path_list); } diff --git a/src/qmmpstarter.cpp b/src/qmmpstarter.cpp index 4aab25da6..0ebf766fc 100644 --- a/src/qmmpstarter.cpp +++ b/src/qmmpstarter.cpp @@ -19,16 +19,17 @@ ***************************************************************************/ #include <QApplication> -#include <QTcpSocket> +#include "unixdomainsocket.h" #include <unistd.h> #include "mainwindow.h" #include "version.h" #include "qmmpstarter.h" -#include "guard.h" -QMMPStarter::QMMPStarter(int argc,char ** argv,QObject* parent) : QObject(parent),mw(0) +#define MAXCOMMANDSIZE 64 + +QMMPStarter::QMMPStarter(int argc,char ** argv,QObject* parent) : QObject(parent),mw(NULL) { QStringList tmp; for(int i = 1;i < argc;i++) @@ -59,52 +60,40 @@ QMMPStarter::QMMPStarter(int argc,char ** argv,QObject* parent) : QObject(parent qFatal("QMMP: Unknown command..."); exit(1); } - - if(Guard::exists(QApplication::applicationFilePath())) - { - m_tcpSocket = new QTcpSocket(this); - connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(displayError(QAbstractSocket::SocketError))); - connect(m_tcpSocket, SIGNAL(connected()),this, SLOT(writeCommand())); - - m_tcpSocket->connectToHost("127.0.0.1",TCPSERVER_PORT_NUMBER + getuid()); - - } - else - { - Guard::create(QApplication::applicationFilePath()); - QStringList arg_l = argString.split("\n", QString::SkipEmptyParts); - mw = new MainWindow(arg_l,0); - } + + m_sock = new UnixDomainSocket(this); + if(m_sock->bind(UDS_PATH)) + { + startMainWindow(); + } + else if(!m_sock->alive(UDS_PATH)){ + // Socket is present but not connectable - application was terminated previously??? + unlink(UDS_PATH); + if(m_sock->bind(UDS_PATH)) + { + startMainWindow(); + } + else + { + qDebug("Fatal socket error, exiting"); + exit(1); + } + } + else // socket is alive, qmmp application is already running. passing command to it! + writeCommand(); } -void QMMPStarter::displayError(QAbstractSocket::SocketError socketError) +QMMPStarter::~ QMMPStarter() { - switch (socketError) - { - case QAbstractSocket::RemoteHostClosedError: - break; - case QAbstractSocket::HostNotFoundError: - qWarning("The host was not found"); - break; - case QAbstractSocket::ConnectionRefusedError: - qWarning("The connection was refused by the peer. "); - break; - default: - qWarning("The following error: %s:",qPrintable(m_tcpSocket->errorString())); - } - - Guard::create(QApplication::applicationFilePath()); - mw = new MainWindow(argString.split("\n", QString::SkipEmptyParts),0); + qWarning("QMMPStarter::~ QMMPStarter()"); + if(mw) delete mw; } -QMMPStarter::~ QMMPStarter() +void QMMPStarter::startMainWindow() { - if(mw) - { - Guard::destroy(QApplication::applicationFilePath()); - delete mw; - } + connect(m_sock, SIGNAL(readyRead()),this, SLOT(readCommand())); + QStringList arg_l = argString.split("\n", QString::SkipEmptyParts); + mw = new MainWindow(arg_l,0); } void QMMPStarter::writeCommand() @@ -117,18 +106,29 @@ void QMMPStarter::writeCommand() QByteArray barray; barray.append(workingDir); barray.append(argString); - - m_tcpSocket->write(barray); - m_tcpSocket->flush(); + m_sock->writeDatagram ( barray.data(),UDS_PATH); } else { - qWarning("It seems that another version of application is already running ...\n"); printUsage(); } - m_tcpSocket->close(); - QApplication::quit(); + exit(0); +} + +void QMMPStarter::readCommand() +{ + QByteArray inputArray; + inputArray.resize(MAXCOMMANDSIZE); + bzero(inputArray.data(),inputArray.size()); + m_sock->readDatagram(inputArray.data(), inputArray.size()); + QStringList slist = QString(inputArray).split("\n",QString::SkipEmptyParts); + QString cwd = slist.takeAt(0); + if(mw) + { + mw->processCommandArgs(slist,cwd); + } + } void QMMPStarter::printUsage() @@ -154,3 +154,5 @@ void QMMPStarter::printVersion() qWarning("QMMP version: %s",QMMP_STR_VERSION); } + + diff --git a/src/qmmpstarter.h b/src/qmmpstarter.h index b3094eb69..c859496cf 100644 --- a/src/qmmpstarter.h +++ b/src/qmmpstarter.h @@ -25,14 +25,14 @@ #include <QAbstractSocket> #include <QStringList> -class QTcpSocket; +class UnixDomainSocket; class MainWindow; /*! * QMMPStarter represents wrapper object that is responsible * for proper QMMP initialization(only one instance of running - * MainWindow) and passing command line args to the TcpServer. + * MainWindow) and passing command line args to application. * @author Vladimir Kuznetsov <vovanec@gmail.com> */ class QMMPStarter : public QObject @@ -42,15 +42,13 @@ public: QMMPStarter(int argc,char ** argv,QObject* parent = 0); ~QMMPStarter(); protected slots: - /*! - * Displays error message. - */ - void displayError(QAbstractSocket::SocketError socketError); /*! - * Passes command args to the running TCP server + * Passes command args to the running application */ void writeCommand(); + + void readCommand(); private: /*! * Prints usage @@ -61,9 +59,11 @@ private: * Prints version of program */ void printVersion(); + + void startMainWindow(); private: MainWindow* mw; - QTcpSocket* m_tcpSocket; + UnixDomainSocket* m_sock; QString argString; }; diff --git a/src/src.pro b/src/src.pro index a7d321a73..9355db692 100644 --- a/src/src.pro +++ b/src/src.pro @@ -47,16 +47,15 @@ HEADERS += mainwindow.h \ playlistformat.h \ playlistcontrol.h \ version.h \ - tcpserver.h \ qmmpstarter.h \ - guard.h \ eqpreset.h \ preseteditor.h \ jumptotrackdialog.h \ aboutdialog.h \ timeindicator.h \ keyboardmanager.h \ - filedialog.h + filedialog.h \ + unixdomainsocket.h SOURCES += mainwindow.cpp \ @@ -96,15 +95,14 @@ SOURCES += mainwindow.cpp \ playlistformat.cpp \ playlistcontrol.cpp \ qmmpstarter.cpp \ - tcpserver.cpp \ - guard.cpp \ eqpreset.cpp \ preseteditor.cpp \ jumptotrackdialog.cpp \ aboutdialog.cpp \ timeindicator.cpp \ keyboardmanager.cpp \ - filedialog.cpp + filedialog.cpp \ + unixdomainsocket.cpp diff --git a/src/tcpserver.cpp b/src/tcpserver.cpp deleted file mode 100644 index 735df2716..000000000 --- a/src/tcpserver.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include <QStringList> -#include <QApplication> -#include <QTcpSocket> -#include <QRegExp> -#include <QTimer> - -#include <unistd.h> - -#include "mainwindow.h" -#include "tcpserver.h" -#include "version.h" - -TcpServer::TcpServer(MainWindow* parent) : QTcpServer(parent) , m_mainWindow(parent) -{ - if (!listen(QHostAddress::LocalHost,TCPSERVER_PORT_NUMBER + getuid())) - { - qFatal("Unable to start the server: %s ",qPrintable(errorString())); - QApplication::exit(1); - } - - connect(this, SIGNAL(newConnection()), this, SLOT(handleNewConnection())); - qDebug("TcpServer running at localost port %d",TCPSERVER_PORT_NUMBER + getuid()); -} - -void TcpServer::handleNewConnection() -{ - clientConnection = nextPendingConnection(); - connect(clientConnection, SIGNAL(readyRead()),this, SLOT(readCommand())); -} - - -void TcpServer::readCommand() -{ - QByteArray inputArray(clientConnection->readAll()); - QStringList slist = QString(inputArray).split("\n",QString::SkipEmptyParts); - QString cwd = slist.takeAt(0); - m_mainWindow->processCommandArgs(slist,cwd); - - if(clientConnection) - { - clientConnection->disconnectFromHost(); - if(clientConnection) - delete clientConnection; - } -} - - - - diff --git a/src/tcpserver.h b/src/tcpserver.h deleted file mode 100644 index 4438f712c..000000000 --- a/src/tcpserver.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef _TCPSERVER_H -#define _TCPSERVER_H - -#include <QTcpServer> -#include <QPointer> - -class TcpSocket; -class MainWindow; - -/*! - * Class TcpServer represents server for frocessing external command line args. - @author Vladimir Kuznetsov <vovanec@gmail.com> - */ - -class TcpServer : public QTcpServer -{ -Q_OBJECT -public: - TcpServer(MainWindow* parent = 0); -protected slots: - void handleNewConnection(); - /*! - * Reads external commands and dispatches it to the MainWindow - */ - void readCommand(); -private: - MainWindow* m_mainWindow; - QPointer <QTcpSocket>clientConnection; -}; - -#endif diff --git a/src/unixdomainsocket.cpp b/src/unixdomainsocket.cpp new file mode 100644 index 000000000..ecf8aa6f0 --- /dev/null +++ b/src/unixdomainsocket.cpp @@ -0,0 +1,67 @@ +#include <unistd.h> +#include <strings.h> +#include <string.h> +#include <errno.h> + +#include "unixdomainsocket.h" + + +UnixDomainSocket::UnixDomainSocket(QObject * parent ) : QUdpSocket(parent){ + _binded = false; + _s = socket(AF_UNIX, SOCK_DGRAM, 0); + this->setSocketDescriptor(_s); +} + +UnixDomainSocket::~UnixDomainSocket(){ + + if(_binded){ + ::unlink(_local.sun_path); + } +} + +bool UnixDomainSocket::bind(const QString& path){ + + int len; + bzero(&_local,sizeof(_local)); + _local.sun_family = AF_UNIX; + strcpy(_local.sun_path,path.toLocal8Bit().data()); + len = strlen(_local.sun_path) + sizeof(_local.sun_family); + bool res = !(::bind(_s, (struct sockaddr *)&_local, len)); + if(res) + _binded = true; + return res; +} + + +bool UnixDomainSocket::alive(const QString& path) +{ + socklen_t len; + struct sockaddr_un server; + bzero(&server,sizeof(server)); + server.sun_family = AF_UNIX; + strcpy(server.sun_path,path.toLocal8Bit().data()); + len = strlen(server.sun_path) + sizeof(server.sun_family); + + if (::connect(_s, (struct sockaddr *)&server, len) == -1) + { + perror("connect"); + return false; + } + return true; +} + +void UnixDomainSocket::writeDatagram(const char* command,const QString& path) +{ + socklen_t len; + struct sockaddr_un server; + bzero(&server,sizeof(server)); + server.sun_family = AF_UNIX; + strcpy(server.sun_path,path.toLocal8Bit().data()); + + len = strlen(server.sun_path) + sizeof(server.sun_family); + + sendto(_s,command,strlen(command),0,(struct sockaddr*)&server,len); +} + + + diff --git a/src/unixdomainsocket.h b/src/unixdomainsocket.h new file mode 100644 index 000000000..7538e685a --- /dev/null +++ b/src/unixdomainsocket.h @@ -0,0 +1,46 @@ +#ifndef UNIXDOMAINSOCKET_H +#define UNIXDOMAINSOCKET_H + +#include <QUdpSocket> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <linux/un.h> + + +/*! + * UnixDomainSocket class is a wrapper around the unix domain sockets implementation. + * Used for QMMP interprocess communications. + * @author Vladimir Kuznetsov <vovanec@gmail.com> + */ +class UnixDomainSocket : public QUdpSocket +{ +Q_OBJECT +public: + UnixDomainSocket(QObject * parent = 0 ); + + /*! + * Try to bind socket to \b path. Returns \b true on success, otherwise \b false + */ + bool bind(const QString& file); + + /*! + * Checks if socket at \b path path is alive( i.e. connectable). + */ + bool alive(const QString& path); + ~UnixDomainSocket(); + +public slots: + /*! + * Sends the datagram \b command to the socket at \b path path. + */ + void writeDatagram(const char* command,const QString& path); +private: + unsigned int _s; + struct sockaddr_un _local; + bool _binded; +}; + + +#endif + diff --git a/src/version.h b/src/version.h index 0d621bacf..61fbc902e 100644 --- a/src/version.h +++ b/src/version.h @@ -1,10 +1,11 @@ #ifndef _QMMP_VERSION_H #define _QMMP_VERSION_H -#define QMMP_VERSION 0.2.0 +#define QMMP_VERSION 0.1.4 -#define QMMP_STR_VERSION "0.2.0" +#define QMMP_STR_VERSION "0.1.4" -#define TCPSERVER_PORT_NUMBER 33000 +#define LISTEN_PORT_BASE 33000 +#define UDS_PATH "/tmp/qmmp.sock" #endif |
