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 }