File indexing completed on 2024-04-21 04:47:49

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Shane King <kde@dontletsstart.com>                                *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "AmarokProcess.h"    
0018 #include "core/support/Debug.h"
0019 
0020 #include <QTextCodec>
0021 
0022 #include <fcntl.h>
0023 #include <sys/time.h>
0024 #include <sys/resource.h>
0025 #include <unistd.h>
0026 
0027 AmarokProcess::AmarokProcess(QObject *parent) 
0028     : KProcess(parent), lowPriority(false) 
0029 {
0030     connect( this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
0031              this, QOverload<>::of(&AmarokProcess::finished) );
0032     connect( this, &QProcess::readyReadStandardOutput, this, &AmarokProcess::readyReadStandardOutput );
0033     connect( this, &QProcess::readyReadStandardError, this, &AmarokProcess::readyReadStandardError );
0034 }
0035 
0036 /** 
0037  * Due to xine-lib, we have to make KProcess close all fds, otherwise we get "device is busy" messages
0038  * exploiting setupChildProcess(), a virtual method that
0039  * happens to be called in the forked process
0040  * See bug #103750 for more information.
0041  */
0042 void
0043 AmarokProcess::setupChildProcess()
0044 {
0045     KProcess::setupChildProcess();
0046 
0047 #ifdef Q_OS_UNIX
0048     // can't get at the fds that QProcess needs to keep around to do its status
0049     // tracking , but fortunately it sets them to close on exec anyway, so if
0050     // we do likewise to everything then we should be ok.
0051     for(int i = sysconf(_SC_OPEN_MAX) - 1; i > 2; i--)
0052         fcntl(i, F_SETFD, FD_CLOEXEC);
0053 
0054     if( lowPriority )
0055         setpriority( PRIO_PROCESS, 0, 19 );
0056 #endif
0057 }
0058 
0059 void
0060 AmarokProcess::start()
0061 {
0062     KProcess::start();
0063 
0064 #ifdef Q_OS_WIN32
0065     if( lowPriority )
0066         SetPriorityClass( QProcess::pid()->hProcess, IDLE_PRIORITY_CLASS );
0067 #endif
0068 }
0069 
0070 void
0071 AmarokProcess::finished() // SLOT
0072 {
0073     Q_EMIT processExited( this );
0074 }
0075 
0076 void
0077 AmarokProcess::readyReadStandardOutput() // SLOT
0078 {
0079     Q_EMIT receivedStdout( this );
0080 }
0081 
0082 void
0083 AmarokProcess::readyReadStandardError() // SLOT
0084 {
0085     Q_EMIT receivedStderr( this );
0086 }
0087 
0088 // AmarokProcIO
0089 AmarokProcIO::AmarokProcIO ( QObject *parent )
0090     : AmarokProcess( parent ), codec( QTextCodec::codecForName( "UTF-8" ) )
0091 {
0092 }
0093 
0094 bool 
0095 AmarokProcIO::writeStdin (const QString &line)
0096 {
0097     return write( codec->fromUnicode( line + '\n' ) ) > 0;
0098 }
0099 
0100 int 
0101 AmarokProcIO::readln (QString &line)
0102 {
0103     QByteArray bytes = readLine();
0104     if (bytes.length() == 0)
0105     {
0106         return -1;
0107     }
0108     else
0109     {
0110         // convert and remove \n
0111         line = codec->toUnicode( bytes.data(), bytes.length() - 1);
0112         return line.length();
0113     }
0114 }
0115 
0116 void
0117 AmarokProcIO::start()
0118 {
0119     connect (this, &AmarokProcIO::readyReadStandardOutput, this, &AmarokProcIO::readyReadStandardOutput);
0120 
0121     KProcess::start ();
0122 }
0123 
0124 void 
0125 AmarokProcIO::readyReadStandardOutput()
0126 {
0127     if( canReadLine() )
0128         Q_EMIT readReady( this );
0129 }
0130 
0131 // AmarokShellProcess
0132 AmarokShellProcess &
0133 AmarokShellProcess::operator<<(const QString& arg)
0134 {
0135     if( program().isEmpty() )
0136         setShellCommand( arg );
0137     else
0138         AmarokProcess::operator<<( arg );
0139     return *this;
0140 }
0141 
0142 AmarokShellProcess &
0143 AmarokShellProcess::operator<<(const QStringList& args)
0144 {
0145     foreach( const QString &arg, args )
0146         *this << arg;
0147     return *this;
0148 }