/**************************************************************************** ** QMPlayerWidget - class ** ** Created: Fri Dec 10 12:09:08 2004 ** by: Varol Okan using kate editor ** ** This class implements the MPLayerWidget ** MediaInterface to this class for integration in QDVDAUthor is MPlayerWidget ** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 see: http://www.fsf.org/licensing/licenses/gpl-howto.html ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "xml_mplayer.h" #include "qplayer_global.h" #include "qmplayerwidget.h" QMPlayerWidget::QMPlayerWidget(QWidget *pParent, const char *pName, WFlags iFlags) : QWidget (pParent, pName, iFlags) { m_iExitError = -1; m_iSeekValue = 3; m_fLength = 0.0; m_qsScreenshotName = QString (MPLAYER_TEMP_FILE); m_bInPauseMode = false; m_pMasterProcess = new QProcess; m_rxParseElapsedTime = QRegExp ("V:(.*[0-9]) "); m_rxParseElapsedTime.setMinimal(true); m_rxParseLength = QRegExp ("ID_LENGTH=([0-9]*)"); // Setting some defaults m_listPluginOptions.append (QString("x11")); m_listPluginOptions.append (QString("")); m_listPluginOptions.append (QString("alsa")); m_listPluginOptions.append (QString("")); QObject::connect (m_pMasterProcess, SIGNAL(readyReadStdout()), this, SLOT (slotReadStdout ())); QObject::connect (m_pMasterProcess, SIGNAL(readyReadStderr()), this, SLOT (slotReadStderr ())); QObject::connect (m_pMasterProcess, SIGNAL(processExited ()), this, SLOT (slotProcessExited ())); QObject::connect (m_pMasterProcess, SIGNAL(wroteToStdin ()), this, SLOT (slotWroteToStdin ())); QObject::connect (m_pMasterProcess, SIGNAL(launchFinished ()), this, SLOT (slotLaunchFinished ())); // And finally load the initFile loadInitFile(); } QMPlayerWidget::~QMPlayerWidget() { if (m_pMasterProcess) delete m_pMasterProcess; } bool QMPlayerWidget::start(QStringList *pEnvironment) { m_bInPauseMode = false; if (m_pMasterProcess->isRunning()) return false; QStringList listCommand; m_pMasterProcess->clearArguments(); listCommand.append(QString("mplayer")); listCommand.append(QString("-zoom")); // Automatically adjust to window size listCommand.append(QString("-noautosub")); listCommand.append(QString("-cache")); listCommand.append(QString("1024")); listCommand.append(QString("-double")); listCommand.append(QString("-loop")); listCommand.append(QString("0")); listCommand.append(QString("-noquiet")); listCommand.append(QString("-ontop")); //listCommand.append(QString("-nosound")); listCommand.append(QString("-osdlevel")); listCommand.append(QString("0")); listCommand.append(QString("-wid")); listCommand.append(QString("%1").arg(winId())); listCommand.append(QString("-slave")); if (!m_listPluginOptions[QMPlayerWidget::AudioPlugin].isEmpty()) { listCommand.append(QString("-ao")); listCommand.append(QString("%1%2").arg(m_listPluginOptions[QMPlayerWidget::AudioPlugin]).arg(m_listPluginOptions[QMPlayerWidget::AudioPluginOptions])); } listCommand.append(QString("-vo")); if (m_listPluginOptions[QMPlayerWidget::VideoPlugin].isEmpty()) listCommand.append(QString("x11")); else listCommand.append(QString("%1%1").arg(m_listPluginOptions[QMPlayerWidget::VideoPlugin]).arg(m_listPluginOptions[QMPlayerWidget::VideoPluginOptions])); listCommand.append(QString("-xy")); // Scales it by keeping aspect ratio listCommand.append(QString("%1").arg(width())); listCommand.append(QString("-identify")); listCommand.append(QString("-framedrop")); listCommand.append(QString("--")); listCommand.append(QString("%1").arg(m_qsFileName)); // -ss 01:10:00 seeks to 1 hour 10 min m_fLength = 0.0; m_pMasterProcess->setArguments (listCommand); emit (signalMPlayerStarted()); return m_pMasterProcess->start(pEnvironment); } void QMPlayerWidget::loadInitFile () { QFileInfo fileInfo; QString qsPlayerIniFile; qsPlayerIniFile = QDir::homeDirPath(); qsPlayerIniFile.append(MPLAYER_INIT_FILE); // Assign the file QFile iniFile(qsPlayerIniFile); if (!iniFile.open(IO_ReadWrite)) return; // Try to get the right xml contents ... QDomDocument xmlDoc( XML_DOCTYPE_MPLAYER ); if (!xmlDoc.setContent (&iniFile)) { // Error handling ... iniFile.close(); printf ( (const char *) QObject::tr ("MPlayer xml init file <%1> seems to be defective. Re-setting values.\n").arg(qsPlayerIniFile)); saveInitFile(); return; } // Here is the main loop to extract the info ... QDomElement searchXMLTree; QDomElement docElem = xmlDoc.documentElement(); QString domText = docElem.tagName(); QDomNode xmlNode = docElem.firstChild(); QString qsVersion = docElem.attributeNode(MPLAYER_VERSION).value(); if (domText == MPLAYER_INI) { // First we take care of the QDVDAuthor variables ... while( !xmlNode.isNull() ) { searchXMLTree = xmlNode.toElement(); domText = searchXMLTree.text(); if (MPLAYER_VIDEO_PLUGIN == searchXMLTree.tagName () ) { m_listPluginOptions[QMPlayerWidget::VideoPluginOptions] = searchXMLTree.attributeNode(MPLAYER_ATTRIB_PLUGIN_OPTIONS).value(); m_listPluginOptions[QMPlayerWidget::VideoPlugin] = searchXMLTree.text(); } else if (MPLAYER_AUDIO_PLUGIN == searchXMLTree.tagName () ) { m_listPluginOptions[QMPlayerWidget::AudioPluginOptions] = searchXMLTree.attributeNode(MPLAYER_ATTRIB_PLUGIN_OPTIONS).value(); m_listPluginOptions[QMPlayerWidget::AudioPlugin] = searchXMLTree.text(); } else printf ("Warning: MPlayer::loadHistory -=> wrong XML Node <%s>\nContinuing ...\n", (const char *)searchXMLTree.tagName()); // Go to the next node ... xmlNode = xmlNode.nextSibling(); } } iniFile.close(); } void QMPlayerWidget::saveInitFile () { QFileInfo fileInfo; QString qsPlayerIniFile; qsPlayerIniFile = QDir::homeDirPath(); qsPlayerIniFile.append(MPLAYER_INIT_FILE); // First we create the document, ... QDomText domText; QDomElement elem, rootElem; QDomDocument xmlDoc( XML_DOCTYPE_MPLAYER ); rootElem = xmlDoc.createElement ( MPLAYER_INI ); rootElem.setAttribute( MPLAYER_VERSION, "0.0.9" ); elem = xmlDoc.createElement ( MPLAYER_VIDEO_PLUGIN ); domText = xmlDoc.createTextNode ( m_listPluginOptions[QMPlayerWidget::VideoPlugin] ); elem.setAttribute( MPLAYER_ATTRIB_PLUGIN_OPTIONS, m_listPluginOptions[QMPlayerWidget::VideoPluginOptions] ); elem.appendChild ( domText ); rootElem.appendChild( elem ); elem = xmlDoc.createElement ( MPLAYER_AUDIO_PLUGIN ); domText = xmlDoc.createTextNode ( m_listPluginOptions[QMPlayerWidget::AudioPlugin] ); elem.setAttribute( MPLAYER_ATTRIB_PLUGIN_OPTIONS, m_listPluginOptions[QMPlayerWidget::AudioPluginOptions] ); elem.appendChild ( domText ); rootElem.appendChild( elem ); xmlDoc.appendChild( rootElem ); // Assign the file QFile iniFile(qsPlayerIniFile); if (!iniFile.open(IO_ReadWrite)) return; QString xml = xmlDoc.toString(); iniFile.writeBlock(xml, qstrlen (xml)); iniFile.close(); } void QMPlayerWidget::setFilename(const QString &qsFileName) { QString qsBuffer; // Here we set the global file name. m_qsFileName = qsFileName; if (m_pMasterProcess->isRunning ()) { qsBuffer = QString ("loadfile %1\n").arg(qsFileName); writeToStdin (qsBuffer); m_fLength = 0.0; } } void QMPlayerWidget::slotReadStdout () { QString qsStdout(m_pMasterProcess->readStdout()); if (qsStdout.length() == 0) return; int iTemp, iElapsedTime, iElapsedLength, iSec, iMin, iHour; QString qsElapsedTime; iTemp = m_rxParseElapsedTime.match(qsStdout); iElapsedLength = 0; if (iTemp != -1) { float fElapsedTime = m_rxParseElapsedTime.cap(1).toFloat(); iElapsedTime = (int)fElapsedTime; if ( m_fLength > 0.0 ) iElapsedLength = (int)(fElapsedTime / m_fLength * 65535.0 ); iHour = (int) (fElapsedTime / 3600.0); iMin = (int)((fElapsedTime-iHour*3600)/60.0); iSec = (int) (fElapsedTime-iHour*3600-iMin*60); qsElapsedTime = qsElapsedTime.sprintf ("%02d:%02d:%02d.%03d", iHour, iMin, iSec, (uint)((fElapsedTime - iElapsedTime)*1000.0)); emit (signalNewPosition ( iElapsedLength, qsElapsedTime ) ); emit (signalNewPosition ( (int)(fElapsedTime * 1000.0) ) ); } if ( m_rxParseLength.search(qsStdout) > -1 ) { m_fLength = m_rxParseLength.cap (1).toFloat (); } } void QMPlayerWidget::slotReadStderr () { QString qsStderr(m_pMasterProcess->readStdout()); if (qsStderr.length() == 0) return; } void QMPlayerWidget::slotProcessExited () { if (m_pMasterProcess->normalExit()) m_iExitError = m_pMasterProcess->exitStatus(); emit (signalMPlayerExited(m_iExitError)); emit (signalPlaybackFinished ()); m_fLength = 0.0; } void QMPlayerWidget::slotWroteToStdin () { } void QMPlayerWidget::slotLaunchFinished () { } void QMPlayerWidget::writeToStdin(QString &qsBuffer) { m_pMasterProcess->writeToStdin(qsBuffer.latin1()); } void QMPlayerWidget::slotForward() { slotSeek(m_iSeekValue,0); } void QMPlayerWidget::slotBack() { slotSeek(-m_iSeekValue,0); } void QMPlayerWidget::slotPlay() { if (m_bInPauseMode) slotPause (); if (m_pMasterProcess->isRunning()) return; start(); } void QMPlayerWidget::slotPause() { m_bInPauseMode = !m_bInPauseMode; QString qsBuffer="pause\n"; writeToStdin (qsBuffer); } void QMPlayerWidget::slotStop() { if (m_bInPauseMode) slotPause (); if (m_pMasterProcess->isRunning()) { QString qsBuffer="quit\n"; writeToStdin (qsBuffer); } m_bInPauseMode = false; m_fLength = 0.0; } void QMPlayerWidget::slotSetSpeed(float fValue) { QString qsBuffer = QString("speed_set %1\n").arg(fValue); writeToStdin (qsBuffer); } void QMPlayerWidget::slotSetVolume(float fValue) { // The slave mode seems to take relative values for the volume, // thus to quiet things down values between [0.0 and 1.0[ // To increase volume values between [1.0 and oo[ // are to be set. // Note: The volume does only depend on the number of times you set the // volume and not on the actual value. // I.e. 10*1.1 is the same as 10*1.0000001 static float m_fOldVolume = 1.0f; double fVolume = fValue - m_fOldVolume + 1.0; m_fOldVolume = fValue; QString qsBuffer = QString ( "volume %1\n" ).arg( fVolume ); writeToStdin ( qsBuffer ); } void QMPlayerWidget::slotFullscreen() { QString qsBuffer="vo_fullscreen\n"; writeToStdin(qsBuffer); } void QMPlayerWidget::slotSeek(float fValue,int iMode) { QString qsBuffer; if (iMode == 0) // seek relative qsBuffer.sprintf("seek %d %d\n", (int)fValue, iMode); else if (iMode == 1) // seek in % of total movie qsBuffer.sprintf("seek %f %d\n", fValue, iMode); else if (iMode == 2) // seek in absolute total movie qsBuffer.sprintf("seek %d %d\n", (int)fValue, iMode); else { printf ("Bad seeking mode, only 1 and 0 allowed\n"); return; } writeToStdin(qsBuffer); } void QMPlayerWidget::slotSetSeek(int iNewValue) { m_iSeekValue=iNewValue; } // Non mandatory functions. void QMPlayerWidget::setAspectRatio (uint iAspectRatio) { // Can be ASPECT_AUTO, ASPECT_34, ASPECT_169, or ASPECT_SQUARE QString qsBuffer; float fAspectRatio = 1.0f; switch (iAspectRatio) { case ASPECT_AUTO: return; break; case ASPECT_34: fAspectRatio = 3.0 / 4.0; break; case ASPECT_169: fAspectRatio = 16.0 / 9.0; break; case ASPECT_SQUARE: default: fAspectRatio = 1.0; break; } qsBuffer.sprintf("switch_aspect %f\n", fAspectRatio); writeToStdin(qsBuffer); } bool QMPlayerWidget::isPlaying() { return m_pMasterProcess->isRunning(); } void QMPlayerWidget::playChapter (int iChapter) { QString qsBuffer; qsBuffer.sprintf("pt_step %d\n", iChapter); writeToStdin(qsBuffer); }