📄 interpreter_cmd.cpp
字号:
/*************************************************************************** * Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> * * * * 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. * ***************************************************************************/#include <math.h>#include <errno.h>#include <fcntl.h>#include <string.h>#include <sys/ipc.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#include <qfile.h>#include <qapplication.h>#include <kdebug.h>#include <klocale.h>#include <kmessagebox.h>#include <kprocess.h>#include <ktempfile.h>#include "interpreter_cmd.h"ProcessData :: ProcessData (){ KTempFile* tmp[2]; tmp[0] = new KTempFile(); tmp[1] = new KTempFile(); tmp[0]->close(); tmp[1]->close(); names[0]=QFile::encodeName( tmp[0]->name() ); names[1]=QFile::encodeName( tmp[1]->name() ); tmp[0]->unlink(); tmp[1]->unlink(); delete tmp[0]; delete tmp[1]; mkfifo( names[0].toAscii().constData() , S_IRUSR | S_IWUSR ); mkfifo( names[1].toAscii().constData() , S_IRUSR | S_IWUSR ); fds[0]=open ( names[0].toAscii().constData(), O_RDWR ); fds[1]=open ( names[1].toAscii().constData(), O_RDWR );}ProcessData :: ~ProcessData(){ close (fds[0]); close (fds[1]); QFile::remove ( names[0] ); QFile::remove ( names[1] );}QPixmap* GSInterpreterCMD::takePixmap(){ kDebug(4655) << "taking pixmap" << endl; QPixmap * x=m_pixmap; m_pixmap=0; return x;}GSInterpreterCMD::GSInterpreterCMD( const QString & fileName ) : m_pixmap ( 0 ), m_process ( 0 ), m_structurePending( false ), m_magnify ( 1 ), m_aaText (1), m_aaGfx (1), m_pfonts (false), m_orientation ( CDSC_PORTRAIT ), m_width ( 0 ), m_height ( 0 ), m_name ( fileName ){ kDebug(4655) << "Constructing async interpreter!" << endl; connect(this, SIGNAL(finished()), this, SLOT(threadFinished()));}GSInterpreterCMD::~GSInterpreterCMD(){ if (!m_pixmap) delete m_pixmap; if ( interpreterRunning() ) stop(false); // remove (crashes okular somehow, probably because // the destuction thread does the same a line higher /* this should not be needed! if (m_stoppingPids.count() > 0) { QMapIterator<pid_t,ProcessData*> it, end=m_stoppingPids.end(); while ( it != end ) { ProcessData *p=it.data(); ++it; delete p; } }*/ m_stoppingPids.clear();// unlock();}void GSInterpreterCMD::destroyInternalProcess(KProcess * stop){ pid_t pId=stop->pid(); kDebug(4655) << "Destroy thread pid " << getpid() << " of " << pId << endl; int x=1; ProcessData *mem=m_stoppingPids[pId]; write(mem->fds[0],&x,sizeof(int)); stop->wait(); kDebug(4655) << "Normal exit : " << !stop->isRunning() << endl; // give it the time to close the interpreter before we kill it if( stop->isRunning() ) { stop->kill(); stop->wait(5); kDebug(4655) << "after stopping, the proces running: " << stop->isRunning() << endl; if( stop->isRunning() ) stop->kill( SIGKILL ); } m_stoppingPids.remove( pId ); delete stop; delete mem;}bool GSInterpreterCMD::ready(){ return !interpreterLock.locked();}bool GSInterpreterCMD::interpreterRunning () { if (m_process==0) { kDebug (4655) << "no process\n"; return false; } else { kDebug(4655) << "running " << m_process->isRunning() << endl; return m_process->isRunning(); }}void GSInterpreterCMD::setStructure(GSInterpreterLib::Position prolog, GSInterpreterLib::Position setup){ kDebug(4655) << "setStructure()" << endl; m_structurePending=true; m_data[0]=prolog; m_data[1]=setup;}bool GSInterpreterCMD::stop(bool async){ kDebug(4655) << "stop()" << endl; // if( !_interpreterBusy ) return; if ( interpreterRunning() ) { if (m_stoppingPids.contains(m_process->pid())) return true; KProcess * stop=m_process; m_stoppingPids.insert ( stop->pid(), m_processData ); m_process=0; kDebug(4655) << "Launching destroy thread" << endl; if (!async) destroyInternalProcess(stop); else { switch ( fork() ) { case -1: // we cant kill it in a fork, kill it outside a fork destroyInternalProcess(stop); break; case 0: destroyInternalProcess(stop); _exit(0); break; default: break; } } } return true;}bool GSInterpreterCMD::startInterpreter(){ kDebug(4655) << "start()" << endl; if ( m_process && m_process->isRunning() ) { kDebug(4655) << "ERROR: starting an interpreter while one is running" << endl; return false; } m_processData=new ProcessData(); m_process = new KProcess; (*m_process) << QString("okulargsasyncgenerator"); // Order of sending: fileName, msgQueueId, media type, magnify, orientation, expected width, height QStringList list; list << m_name << m_processData->names[0] << m_processData->names[1] << m_media.toLower() << QString::number ( m_magnify ) << QString::number ( m_orientation ) << QString::number ( m_width ) << QString::number ( m_height ) << QString::number ( m_pfonts ? 1 : 0 ) << QString::number (m_aaText) << QString::number (m_aaGfx); kDebug(4655) << "Argument count: " << list.count() << endl; (*m_process) << list; /*connect( m_process, SIGNAL( processExited( KProcess* ) ), this, SLOT( slotProcessExited( KProcess* ) ) ); connect( m_process, SIGNAL( receivedStdout( KProcess*, char*, int ) ), this, SLOT( output( KProcess*, char*, int ) ) ); connect( m_process, SIGNAL( receivedStderr( KProcess*, char*, int ) ), this, SLOT( output( KProcess*, char*, int ) ) ); connect( m_process, SIGNAL( wroteStdin( KProcess*) ), this, SLOT( gs_input( KProcess* ) ) );*/ // Finally fire up the interpreter.// kDebug(4500) << "KPSWidget: starting interpreter" << endl; if( m_process->start( KProcess::NotifyOnExit, /*m_usePipe ?*/ KProcess::Stdin | KProcess::Stdout/*KProcess::All*/ /*: KProcess::AllOutput*/ ) ) { kDebug(4655) << "Starting async! " << m_process->pid() << endl; return true; } else { emit error(i18n( "Could not start the libgs helper application of okular. This is most likely " "caused by okulargsasyncgenerator not being installed, or installed to a " "directory not listed in the environment PATH variable."),0); kDebug(4655) << "Could not start helper" << endl; return false; }}void GSInterpreterCMD::setOrientation( int orientation ){ lock(); if( m_orientation != orientation ) { m_orientation = orientation; stop(); } unlock();}void GSInterpreterCMD::setMagnify( double magnify ){ lock(); if( m_magnify != magnify ) { m_magnify = magnify; stop(); } unlock();}void GSInterpreterCMD::setMedia( QString media ){ lock(); if( m_media != media ) { m_media = media; stop(); } unlock();}void GSInterpreterCMD::setPlatformFonts(bool pfonts){ lock(); if( m_pfonts != pfonts ) { m_pfonts = pfonts; stop(); } unlock();}void GSInterpreterCMD::setSize( int w, int h ){ lock(); if ( m_width != w ) { m_width=w; stop(); } if ( m_height != h ) { m_height=h; stop(); } unlock();}void GSInterpreterCMD::setAABits(int text, int graphics){ lock(); if ( m_aaText!= text ) { m_aaText=text; stop(); } if ( m_aaGfx != graphics ) { m_aaGfx=graphics; stop(); } unlock();}bool GSInterpreterCMD::run( GSInterpreterLib::Position pos){ kDebug(4655) << "Running request with size: " << m_width << "x" << m_height << endl; if( !interpreterRunning() ) return false; if ( m_pixmap != 0 ) { kDebug(4655) << "ERROR DELETING PIXMAP, THIS SHOULD NOT HAPPEN" << endl; delete m_pixmap; } // the pixmap to which the generated image will be copied m_pixmap = new QPixmap (m_width, m_height); m_pixmap -> fill(); m_info.pos=pos; m_info.sync=true; m_info.handle=m_pixmap->handle(); if ( isRunning() ) { // in my mind we should never reach here but it seems we do // so wait a bit until the thread has really ended wait(); } start(); return true;}void GSInterpreterCMD::run(){ lock(); // we are inside a thread kDebug(4655)<< "Generation thread started " << getpid() << endl; int x; // pending structural information -> send them if (m_structurePending) { kDebug(4655) << "sending structural data" << endl; PageInfo pageInf; for (int i=0;i<2;i++) { x=0; write ( m_processData->fds[0] , &x, sizeof(int) ); pageInf.sync=false; pageInf.pos=m_data[i]; pageInf.handle=m_info.handle; write( m_processData->fds[0], &pageInf, sizeof(pageInf)); read( m_processData->fds[1],&x,sizeof(int)); } m_structurePending=false; } kDebug(4655)<< "sending page request" << endl; // Communication with the helper looks like this // 1. Sendign a 0 to helper telling it to start a function that processes the request x=0; write ( m_processData->fds[0] , &x, sizeof(int) ); // 2. sending the structure with relevant information write ( m_processData->fds[0], &m_info, sizeof(m_info) ); // 3. we will receive a '3' from the helper when request is done, // the helper will copy the pixmap using XCopyArea read ( m_processData->fds[1], &x, sizeof(int) ); unlock(); kDebug(4655)<< "pximap ready" << endl; if (x==3) { /* kDebug(4655)<< "sending the pximap to generator" << endl; // inform interpreter about PixmaRequest being done QCustomEvent * readyEvent = new QCustomEvent( GS_DATAREADY_ID ); // set sth just to send nonempty readyEvent->setData(&x); QApplication::postEvent( this , readyEvent );*/ } kDebug() << "ME ACABO" << endl;}void GSInterpreterCMD::threadFinished(){ // TODO use x==3 in the if above to set a success variable emit Finished(takePixmap());}/*#include <qdialog.h>#include <qpainter.h>void GSInterpreterCMD::customEvent( QEvent * e ){ if (e->type() == GS_DATAREADY_ID ) { kWarning() << "emitting signal" << endl; QPixmap *pix=takePixmap(); emit Finished(pix); }}*/#include "interpreter_cmd.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -