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 + -
显示快捷键?