Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Wrong Implementation of single instance application

Wrong Implementation of single instance application

Scheduled Pinned Locked Moved Solved General and Desktop
qlocalserverqlocalsocketipcqtsingleapplica
12 Posts 4 Posters 4.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    AyushExel204
    wrote on 12 May 2016, 08:07 last edited by
    #1

    I have developed a media player which is a single instance application. I have implemented it using QLocalSocket and QLocalServer . So, when another media file is opened using the application, it gets added in the playlist of the already running instance of the application. So, the app works fine when I open different media files one by one but when I select multiple media files and press "Enter", only few of them are added to the playlist and the rest are discarded.
    Below is the part of the program which makes it single instance :
    Singleinstance.h

    #ifndef SINGLEINSTANCE_H
    #define SINGLEINSTANCE_H
    
    #include <QObject>
    #include <QDebug>
    #include <QLocalServer>
    #include <QLocalSocket>
    #include <QMediaPlaylist>
    class SingleInstance : public QObject
    {
        Q_OBJECT
    public:
         SingleInstance(QObject *parent = 0, QMediaPlaylist* pl=new QMediaPlaylist);
        ~SingleInstance();
    
        /**
         * @brief Listen for connections
         * @param name
         */
        void listen(QString name);
    
        /**
         * @brief Determines if a previous instance exists
         * @param name
         * @param arg
         * @return
         */
        bool hasPrevious(QString name, QString arg);
    
    signals:
    
        /**
         * @brief Emitted when a new instance is launched
         */
        void newInstance();
    
    
    public slots:
    
        /**
         * @brief Called when a new instance is opened
         */
        void newConnection();
    
        /**
         * @brief Read from the socket
         */
        void readyRead();
    
    private:
        /**
         * @brief Local socket
         */
        QLocalSocket* mSocket;
    
        /**
         * @brief The server
         */
        QLocalServer mServer;
    // Pointer to the playlist of mediaPlayer
        QMediaPlaylist* playlist;
    };
    
    #endif // SINGLEINSTANCE_H
    
    

    singleinstace.cpp

    #include "singleinstance.h"
    SingleInstance::SingleInstance(QObject *parent, QMediaPlaylist *pl) : QObject(parent),playlist(pl)
    {
        connect(&mServer, SIGNAL(newConnection()),this,SLOT(newConnection()));
    }
    
    SingleInstance::~SingleInstance()
    {
    
    mSocket->close();
    }
    
    void SingleInstance::listen(QString name)
    {
        mServer.removeServer(name);
        mServer.listen(name);
    
    
    }
    
    bool SingleInstance::hasPrevious(QString name, QString arg)
    {
    
    
        QLocalSocket socket;
        socket.connectToServer(name, QLocalSocket::ReadWrite);
    
        if(socket.waitForConnected())
        {
           if(!arg.isEmpty()){ QByteArray buffer;
    
           buffer.append(arg);
            socket.write(buffer);
            socket.waitForBytesWritten();
           }
    
            return true;
        }
    
    
        return false;
    
    }
    
    void SingleInstance::newConnection()
    {
        emit newInstance();
    
       mSocket = mServer.nextPendingConnection();
       connect(mSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));
    }
    
    void SingleInstance::readyRead()
    {  //Adding media to the playlist
        playlist->addMedia(QUrl::fromLocalFile(QString::fromStdString(mSocket->readAll().toStdString())));
    
        playlist->setCurrentIndex(playlist->mediaCount()-1);
        mSocket->deleteLater();
    
    }
    
    

    How can I fix this code ? Or is there easier way to accomplish this task ?

    1 Reply Last reply
    0
    • V Offline
      V Offline
      VRonin
      wrote on 12 May 2016, 08:12 last edited by
      #2

      in readyRead could you check that mSocket->bytesAvailable() is the same as buffer.size() in hasPrevious?

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      A 1 Reply Last reply 12 May 2016, 08:17
      0
      • V VRonin
        12 May 2016, 08:12

        in readyRead could you check that mSocket->bytesAvailable() is the same as buffer.size() in hasPrevious?

        A Offline
        A Offline
        AyushExel204
        wrote on 12 May 2016, 08:17 last edited by
        #3

        @VRonin yes they are same

        1 Reply Last reply
        0
        • V Offline
          V Offline
          VRonin
          wrote on 12 May 2016, 08:26 last edited by
          #4

          What's the output of mSocket->readAll() ? could you paste it here?

          P.S.

          playlist->addMedia(QUrl::fromLocalFile(QString(mSocket->readAll())); // no need to use STD string
          
          SingleInstance(QObject *parent = 0, QMediaPlaylist* pl=new QMediaPlaylist /*<- This is horrible and 99% memory leak guaranteed*/);
          

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          A 1 Reply Last reply 12 May 2016, 08:54
          0
          • V VRonin
            12 May 2016, 08:26

            What's the output of mSocket->readAll() ? could you paste it here?

            P.S.

            playlist->addMedia(QUrl::fromLocalFile(QString(mSocket->readAll())); // no need to use STD string
            
            SingleInstance(QObject *parent = 0, QMediaPlaylist* pl=new QMediaPlaylist /*<- This is horrible and 99% memory leak guaranteed*/);
            
            A Offline
            A Offline
            AyushExel204
            wrote on 12 May 2016, 08:54 last edited by AyushExel204 5 Dec 2016, 08:58
            #5

            @VRonin Okay so I selected the 10 audio files and pressed "Enter" and printed the output of mSocket->readAll() . The output is :

            D:\Music\songs\5 second of summer\5 Seconds Of Summer\08 - End Up Here - (www.SongsLover.pk).mp3
            D:\Music\songs\5 second of summer\5 Seconds Of Summer\12 - Amnesia - (www.SongsLover.pk).mp3
            
            
            
            
            
            
            
            D:\Music\songs\5 second of summer\5 Seconds Of Summer\Voodoo Doll.mp3
            

            So it is clear that only 3 files are added in the playlist and the address of other files are just replaced by a new line.

            1 Reply Last reply
            0
            • V Offline
              V Offline
              VRonin
              wrote on 12 May 2016, 09:23 last edited by VRonin 5 Dec 2016, 09:24
              #6

              I suspect it has to do with encoding

              try replacing buffer.append(arg); with

              QDataStream out(&buffer,QIODevice::WriteOnly);
              out << arg;
              

              and replace playlist->addMedia(QUrl::fromLocalFile(QString::fromStdString(mSocket->readAll().toStdString()))); with

              const QByteArray buffer=mSocket->readAll();
              QDataStream in(buffer);
              QString argString;
              in >> argString;
              playlist->addMedia(QUrl::fromLocalFile(argString);
              

              and check that argString has all the lines in it

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              A 1 Reply Last reply 12 May 2016, 09:38
              0
              • V VRonin
                12 May 2016, 09:23

                I suspect it has to do with encoding

                try replacing buffer.append(arg); with

                QDataStream out(&buffer,QIODevice::WriteOnly);
                out << arg;
                

                and replace playlist->addMedia(QUrl::fromLocalFile(QString::fromStdString(mSocket->readAll().toStdString()))); with

                const QByteArray buffer=mSocket->readAll();
                QDataStream in(buffer);
                QString argString;
                in >> argString;
                playlist->addMedia(QUrl::fromLocalFile(argString);
                

                and check that argString has all the lines in it

                A Offline
                A Offline
                AyushExel204
                wrote on 12 May 2016, 09:38 last edited by AyushExel204 5 Dec 2016, 09:40
                #7

                @VRonin Okay so now even when I open a single media file , it is not added in the playlist . So, I have reverted back to the original code. I want to add that, sometimes the program works correctly and all media files that I select are added in the playlist but most of the times few of them are not added , instead just a blank line is added in the playlist.

                K 1 Reply Last reply 12 May 2016, 10:13
                0
                • A AyushExel204
                  12 May 2016, 09:38

                  @VRonin Okay so now even when I open a single media file , it is not added in the playlist . So, I have reverted back to the original code. I want to add that, sometimes the program works correctly and all media files that I select are added in the playlist but most of the times few of them are not added , instead just a blank line is added in the playlist.

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 12 May 2016, 10:13 last edited by
                  #8

                  @AyushExel204

                  You're overwriting the socket pointer when multiple connections are pending

                  mSocket = mServer.nextPendingConnection();
                  connect(mSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));
                  

                  Then you read from incorrect socket(s):

                  playlist->addMedia(QUrl::fromLocalFile(QString::fromStdString(mSocket->readAll().toStdString())));
                  

                  Try this:

                  void SingleInstance::readyRead()
                  { 
                      QLocalSocket * socket = qobject_cast<QLocalSocket *>(sender());
                      playlist->addMedia(QUrl::fromLocalFile(socket->readAll()));
                      // ...
                      socket->deleteLater();
                  }
                  

                  Also I don't understand why you insist on converting QString to std::string and then back again??!

                  Read and abide by the Qt Code of Conduct

                  A 1 Reply Last reply 12 May 2016, 13:45
                  3
                  • V Offline
                    V Offline
                    VRonin
                    wrote on 12 May 2016, 10:17 last edited by
                    #9

                    I still think that if the file path contains non-ASCII this implementation will fail as it converts from QString to QByteArray with no checks

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    K 1 Reply Last reply 12 May 2016, 10:29
                    0
                    • V VRonin
                      12 May 2016, 10:17

                      I still think that if the file path contains non-ASCII this implementation will fail as it converts from QString to QByteArray with no checks

                      K Offline
                      K Offline
                      kshegunov
                      Moderators
                      wrote on 12 May 2016, 10:29 last edited by kshegunov 5 Dec 2016, 10:31
                      #10

                      @VRonin

                      I still think that if the file path contains non-ASCII this implementation will fail as it converts from QString to QByteArray with no checks

                      Yes, it's quite possible.
                      Actually it turns out the QString is implicitly converted to utf8 and then added to the byte array. So it might actually work.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • K kshegunov
                        12 May 2016, 10:13

                        @AyushExel204

                        You're overwriting the socket pointer when multiple connections are pending

                        mSocket = mServer.nextPendingConnection();
                        connect(mSocket,SIGNAL(readyRead()),this,SLOT(readyRead()));
                        

                        Then you read from incorrect socket(s):

                        playlist->addMedia(QUrl::fromLocalFile(QString::fromStdString(mSocket->readAll().toStdString())));
                        

                        Try this:

                        void SingleInstance::readyRead()
                        { 
                            QLocalSocket * socket = qobject_cast<QLocalSocket *>(sender());
                            playlist->addMedia(QUrl::fromLocalFile(socket->readAll()));
                            // ...
                            socket->deleteLater();
                        }
                        

                        Also I don't understand why you insist on converting QString to std::string and then back again??!

                        A Offline
                        A Offline
                        AyushExel204
                        wrote on 12 May 2016, 13:45 last edited by AyushExel204 5 Dec 2016, 13:48
                        #11

                        @kshegunov said:

                        QLocalSocket * socket = qobject_cast<QLocalSocket *>(sender());
                        playlist->addMedia(QUrl::fromLocalFile(socket->readAll()));

                        Thanks .. this fixed my problem . but can you explain what this code does ?

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          jsulm
                          Lifetime Qt Champion
                          wrote on 13 May 2016, 04:54 last edited by
                          #12

                          sender() returns the pointer to the object which emitted the signal (http://doc.qt.io/qt-5.6/qobject.html#sender).
                          In this case it is a pointer to QLocalSocket, so you need to cast it from QObject* to QLocalSocket* using qobject_cast

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          2

                          8/12

                          12 May 2016, 10:13

                          • Login

                          • Login or register to search.
                          8 out of 12
                          • First post
                            8/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved