nmm_engine.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 713 行 · 第 1/2 页

CPP
713
字号
/* NMM - Network-Integrated Multimedia Middleware * * Copyright (C) 2002-2006 *                    NMM work group, *                    Computer Graphics Lab, *                    Saarland University, Germany *                    http://www.networkmultimedia.org * * Maintainer:        Robert Gogolok <gogo@graphics.cs.uni-sb.de> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA  02111-1307 * USA */#include "nmm_engine.h"#include "nmm_kdeconfig.h"#include "nmm_configdialog.h"#include "HostListItem.h"#include "debug.h"#include "plugin/plugin.h"#include <nmm/base/graph/GraphBuilder2.hpp>#include <nmm/base/registry/NodeDescription.hpp>#include <nmm/base/ProxyApplication.hpp>#include <nmm/interfaces/base/sync/ISynchronizedSink.hpp>#include <nmm/interfaces/file/ISeekable.hpp>#include <nmm/interfaces/file/ITrack.hpp>#include <nmm/interfaces/file/IBufferSize.hpp>#include <nmm/interfaces/general/progress/IProgressListener.hpp>#include <nmm/interfaces/general/progress/IProgress.hpp>#include <nmm/interfaces/general/ITrackDuration.hpp>#include <nmm/interfaces/device/audio/IAudioDevice.hpp>#include <nmm/base/ProxyObject.hpp>#include <nmm/utils/NMMConfig.hpp>#include <qapplication.h>#include <qtimer.h>#include <kfileitem.h>#include <klocale.h>#include <kmessagebox.h>#include <kmimetype.h>#include <iostream>#include <kurl.h>NmmEngine* NmmEngine::s_instance;AMAROK_EXPORT_PLUGIN( NmmEngine )NmmEngine::NmmEngine()  : Engine::Base(),    __position(0),    __track_length(0),    __state(Engine::Empty),    __app(NULL),    __endTrack_listener(this, &NmmEngine::endTrack),    __syncReset_listener(this, &NmmEngine::syncReset),    __setProgress_listener(this, &NmmEngine::setProgress),    __trackDuration_listener(this, &NmmEngine::trackDuration),    __composite(NULL),    __playback(NULL),    __display(NULL),    __av_sync(NULL),    __synchronizer(NULL),    __with_video(false),    __seeking(false),    m_localhostonly_errordialog(false){  addPluginProperty( "HasConfigure", "true" );}bool NmmEngine::init(){  DEBUG_BLOCK  s_instance = this;  // disable debug and warning streams  NamedObject::getGlobalInstance().setDebugStream(NULL, NamedObject::ALL_LEVELS);  NamedObject::getGlobalInstance().setWarningStream(NULL, NamedObject::ALL_LEVELS);  // create new NMM application object  __app = ProxyApplication::getApplication(0, 0);  createEnvironmentHostList();  createUserHostList();  connect( this, SIGNAL( hostError( QString, int ) ), SLOT( notifyHostError( QString, int ) ) );  return true;}NmmEngine::~NmmEngine(){  // stop all nodes  stop();  // delete application object  if (__app)    delete __app;}void NmmEngine::checkSecurity(){  const char* home(getenv("HOME"));  NMMConfig nmmconfig( string(home) + string("/.nmmrc") );  bool readpaths_set = false;  bool writepaths_set = false;  string optionvalue("");  nmmconfig.getValue("allowedreadpaths", optionvalue);  if( !optionvalue.empty() )    readpaths_set = true;  optionvalue = "";  nmmconfig.getValue("allowedwritepaths", optionvalue);  if( !optionvalue.empty() )    writepaths_set = true;  QString str;  str += "<html><body>";  str += "Your current NMM setup is insecure.<br/><br/>";  str += "The file <b>.nmmrc</b> in your home directory restricts read and write access for NMM to certain paths.<br/><br/>";  if( !readpaths_set )    str += "<b>allowedreadpaths option is not set</b>. NMM plugins are therefore allowed to read every file the process running NMM is allowed.<br/>";  if( !writepaths_set )    str += "<b>allowedwritepaths option is not set</b>. NMM plugins are therefore allowed to write every file or directory the process running NMM is allowed.<br/>";  str += "<br/>See <a href=\"http://www.networkmultimedia.org/Download/\">http://www.networkmultimedia.org/Download/</a> for general security instructions in the correspoding <i>configure and test NMM</i> section depending on your chosen installation method.";  str += "</body></html>";  if( !writepaths_set || !readpaths_set )    KMessageBox::information(0, str, i18n( "Insecure NMM setup" ), "insecureNmmSetup", KMessageBox::AllowLink );}void NmmEngine::notifyHostError( QString hostname, int error ){  DEBUG_BLOCK  for( QValueList<NmmLocation>::Iterator it = tmp_user_list.begin(); it != tmp_user_list.end(); ++it ) {    if( (*it).hostname() == hostname ) {      (*it).setStatus( error );      break;    }  }  for( QValueList<NmmLocation>::Iterator it = tmp_environment_list.begin(); it != tmp_environment_list.end(); ++it ) {    if( (*it).hostname() == hostname ) {      (*it).setStatus( error );      break;    }  }}Engine::State NmmEngine::state() const{  return __state;}Amarok::PluginConfig* NmmEngine::configure() const{    NmmConfigDialog* dialog = new NmmConfigDialog();    connect( this, SIGNAL( hostError( QString, int ) ), dialog, SLOT( notifyHostError(QString, int ) ) );    return dialog;}bool NmmEngine::load(const KURL& url, bool stream){  DEBUG_BLOCK  static int error;  error = STATUS_UNKNOWN;  // check security options  static bool already_checked = false;  if( !already_checked) {    QTimer::singleShot(100, this, SLOT( checkSecurity() ) );    already_checked = true;  }  // Don't play a track if 'localhost only' error dialog is being shown  if( m_localhostonly_errordialog )    return false;  // play only local files  if( !url.isLocalFile() ) {    debug() << "Currently NMM engine can only play local files!" << endl;    return false;  }  Engine::Base::load(url, stream);  cleanup();  // make the GraphBuilder construct an appropriate graph for the given URL  try {    QStringList hosts;    // node for audio playback    NodeDescription playback_nd("PlaybackNode");    // ALSA or OSS    if( NmmKDEConfig::audioOutputPlugin() == "ALSAPlaybackNode" )        playback_nd = NodeDescription("ALSAPlaybackNode");    // TODO: currently we only support one host for audio playback    if( !(hosts = getSinkHosts()).empty() )        playback_nd.setLocation( hosts.first().ascii() );    // node for video playback    NodeDescription display_nd("XDisplayNode");    // TODO: currently we only support one host for video playback    if( !(hosts = getSinkHosts( false )).empty() )        display_nd.setLocation( hosts.first().ascii() );    GraphBuilder2 gb;    // convert the URL to a valid NMM url    if(!gb.setURL("file://" + string(url.path().ascii())))      throw Exception("Invalid URL given");    ClientRegistry& registry = __app->getRegistry();    // requst playback and audio node {{{    {      //debug() << "##############> ClientRegistry " << endl;      RegistryLock lock(registry);      // get a playback node interface from the registry      try {      list<Response> playback_response = registry.initRequest(playback_nd);      if (playback_response.empty()) // playback node not available        throw( NMMEngineException( playback_nd.getLocation(), NmmEngine::ERROR_PLAYBACKNODE ) );      __playback = registry.requestNode( playback_response.front() );      }      catch( RegistryException ) {        error = NmmEngine::ERROR_PLAYBACKNODE;        throw( NMMEngineException( playback_nd.getLocation(), NmmEngine::ERROR_PLAYBACKNODE ) );      }      catch(...) {        error = NmmEngine::ERROR_PLAYBACKNODE;        throw;      }      // get a display node interface from the registry      try {      list<Response> display_response = registry.initRequest(display_nd);      if (display_response.empty()) // Display Node not available        throw NMMEngineException( display_nd.getLocation(), NmmEngine::ERROR_DISPLAYNODE );      __display = registry.requestNode(display_response.front());      }      catch( RegistryException ) {        error = NmmEngine::ERROR_DISPLAYNODE;        throw NMMEngineException( display_nd.getLocation(), NmmEngine::ERROR_DISPLAYNODE );      }      catch(...) {        error = NmmEngine::ERROR_DISPLAYNODE;        throw;      }      //debug() << "##############< ClientRegistry " << endl;    }//}}}    __av_sync = new MultiAudioVideoSynchronizer();    __synchronizer = __av_sync->getCheckedInterface<IMultiAudioVideoSynchronizer>();    // initialize the GraphBuilder    gb.setMultiAudioVideoSynchronizer(__synchronizer);    gb.setAudioSink(__playback);    gb.setVideoSink(__display);    gb.setDemuxAudioJackTag("audio");    gb.setDemuxVideoJackTag("video");    // create the graph represented by a composite node    __composite = gb.createGraph(*__app);    // if the display node is connected we know we will play a video TODO: what about video without audio?    __with_video = __display->isInputConnected();    debug() << "NMM video playback? " << __with_video << endl;    // set volume for playback node    setVolume( m_volume );    // register the needed event listeners at the display node if video enabled    if(__with_video) {        __display->getParentObject()->registerEventListener(ISyncReset::syncReset_event, &__syncReset_listener);        __display->getParentObject()->registerEventListener(IProgressListener::setProgress_event, &__setProgress_listener);        __display->getParentObject()->registerEventListener(ITrack::endTrack_event, &__endTrack_listener);    }    else { // in other case at the playback node        __playback->getParentObject()->registerEventListener(ISyncReset::syncReset_event, &__syncReset_listener);        __playback->getParentObject()->registerEventListener(IProgressListener::setProgress_event, &__setProgress_listener);        __playback->getParentObject()->registerEventListener(ITrack::endTrack_event, &__endTrack_listener);        (__playback->getParentObject()->getCheckedInterface<ISynchronizedSink>())->setSynchronized(false);    }    __playback->getParentObject()->registerEventListener(ITrackDuration::trackDuration_event, &__trackDuration_listener);    __display->getParentObject()->registerEventListener(ITrackDuration::trackDuration_event, &__trackDuration_listener);    // Tell the node that implements the IProgress interface to send progress events frequently.    IProgress_var progress(__composite->getInterface<IProgress>());    if (progress.get()) {      progress->sendProgressInformation(true);      progress->setProgressInterval(1);    }    // minimize the buffer size to increase the frequency of progress events    IBufferSize_var buffer_size(__composite->getInterface<IBufferSize>());    if (buffer_size.get()) {      buffer_size->setBufferSize(1000);    }    // we don't know the track length yet - we have to wait for the trackDuration event    __track_length = 0;    __seeking = false;    // finally start the graph    if(__playback->isActivated())      __playback->reachStarted();    if(__display->isActivated())      __display->reachStarted();    __composite->reachStarted();    return true;  }  catch ( const NMMEngineException e) {    QString host = e.hostname.c_str();    emit hostError(host, error);    emit statusText( i18n("NMM engine: Stopping playback...") );  }  catch (const Exception& e) {    cerr << e << endl;    QString status = e.getComment().c_str() ;    emit statusText( QString( i18n("NMM engine: ") ) + status );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?