diff --git a/core/audioplayer.cpp b/core/audioplayer.cpp index 3188fe6a0..5e89d4840 100644 --- a/core/audioplayer.cpp +++ b/core/audioplayer.cpp @@ -1,262 +1,263 @@ /*************************************************************************** * Copyright (C) 2007 by Pino Toscano * * * * 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 "audioplayer.h" #include "audioplayer_p.h" // qt/kde includes #include #include #include #include #include #include #include #include // local includes #include "action.h" #include "debug_p.h" #include "sound.h" using namespace Okular; // helper class used to store info about a sound to be played class SoundInfo { public: explicit SoundInfo( const Sound * s = nullptr, const SoundAction * ls = nullptr ) : sound( s ), volume( 0.5 ), synchronous( false ), repeat( false ), mix( false ) { if ( ls ) { volume = ls->volume(); synchronous = ls->synchronous(); repeat = ls->repeat(); mix = ls->mix(); } } const Sound * sound; double volume; bool synchronous; bool repeat; bool mix; }; class PlayData { public: PlayData() : m_mediaobject( nullptr ), m_output( nullptr ), m_buffer( nullptr ) { } void play() { if ( m_buffer ) { m_buffer->open( QIODevice::ReadOnly ); } m_mediaobject->play(); } ~PlayData() { m_mediaobject->stop(); delete m_mediaobject; delete m_output; delete m_buffer; } PlayData(const PlayData &) = delete; PlayData &operator=(const PlayData &) = delete; Phonon::MediaObject * m_mediaobject; Phonon::AudioOutput * m_output; QBuffer * m_buffer; SoundInfo m_info; }; AudioPlayerPrivate::AudioPlayerPrivate( AudioPlayer * qq ) : q( qq ), m_state( AudioPlayer::StoppedState ) { - QObject::connect( &m_mapper, SIGNAL(mapped(int)), q, SLOT(finished(int)) ); } AudioPlayerPrivate::~AudioPlayerPrivate() { stopPlayings(); } int AudioPlayerPrivate::newId() const { int newid = 0; QHash< int, PlayData * >::const_iterator it; QHash< int, PlayData * >::const_iterator itEnd = m_playing.constEnd(); do { newid = KRandom::random(); it = m_playing.constFind( newid ); } while ( it != itEnd ); return newid; } bool AudioPlayerPrivate::play( const SoundInfo& si ) { qCDebug(OkularCoreDebug) ; PlayData * data = new PlayData(); data->m_output = new Phonon::AudioOutput( Phonon::NotificationCategory ); data->m_output->setVolume( si.volume ); data->m_mediaobject = new Phonon::MediaObject(); Phonon::createPath(data->m_mediaobject, data->m_output); data->m_info = si; bool valid = false; switch ( si.sound->soundType() ) { case Sound::External: { QString url = si.sound->url(); qCDebug(OkularCoreDebug) << "External," << url; if ( !url.isEmpty() ) { int newid = newId(); - m_mapper.setMapping( data->m_mediaobject, newid ); + QObject::connect( data->m_mediaobject, &Phonon::MediaObject::finished, q, [this, newid]() { + finished(newid); + }); QUrl newurl; if ( QUrl::fromUserInput(url).isRelative() ) { newurl = m_currentDocument.adjusted(QUrl::RemoveFilename); newurl.setPath(newurl.path() + url ); } else { newurl = QUrl::fromLocalFile(url); } data->m_mediaobject->setCurrentSource( newurl ); m_playing.insert( newid, data ); valid = true; } break; } case Sound::Embedded: { QByteArray filedata = si.sound->data(); qCDebug(OkularCoreDebug) << "Embedded," << filedata.length(); if ( !filedata.isEmpty() ) { qCDebug(OkularCoreDebug) << "Mediaobject:" << data->m_mediaobject; int newid = newId(); - m_mapper.setMapping( data->m_mediaobject, newid ); + QObject::connect( data->m_mediaobject, &Phonon::MediaObject::finished, q, [this, newid]() { + finished(newid); + }); data->m_buffer = new QBuffer(); data->m_buffer->setData( filedata ); data->m_mediaobject->setCurrentSource( Phonon::MediaSource( data->m_buffer ) ); m_playing.insert( newid, data ); valid = true; } break; } } if ( !valid ) { delete data; data = nullptr; } if ( data ) { - QObject::connect( data->m_mediaobject, SIGNAL(finished()), &m_mapper, SLOT(map()) ); qCDebug(OkularCoreDebug) << "PLAY"; data->play(); m_state = AudioPlayer::PlayingState; } return valid; } void AudioPlayerPrivate::stopPlayings() { qDeleteAll( m_playing ); m_playing.clear(); m_state = AudioPlayer::StoppedState; } void AudioPlayerPrivate::finished( int id ) { QHash< int, PlayData * >::iterator it = m_playing.find( id ); if ( it == m_playing.end() ) return; SoundInfo si = it.value()->m_info; // if the sound must be repeated indefinitely, then start the playback // again, otherwise destroy the PlayData as it's no more useful if ( si.repeat ) { it.value()->play(); } else { - m_mapper.removeMappings( it.value()->m_mediaobject ); delete it.value(); m_playing.erase( it ); m_state = AudioPlayer::StoppedState; } qCDebug(OkularCoreDebug) << "finished," << m_playing.count(); } AudioPlayer::AudioPlayer() : QObject(), d( new AudioPlayerPrivate( this ) ) { } AudioPlayer::~AudioPlayer() { delete d; } AudioPlayer * AudioPlayer::instance() { static AudioPlayer ap; return ≈ } void AudioPlayer::playSound( const Sound * sound, const SoundAction * linksound ) { // we can't play null pointers ;) if ( !sound ) return; // we don't play external sounds for remote documents if ( sound->soundType() == Sound::External && !d->m_currentDocument.isLocalFile() ) return; qCDebug(OkularCoreDebug) ; SoundInfo si( sound, linksound ); // if the mix flag of the new sound is false, then the currently playing // sounds must be stopped. if ( !si.mix ) d->stopPlayings(); d->play( si ); } void AudioPlayer::stopPlaybacks() { d->stopPlayings(); } AudioPlayer::State AudioPlayer::state() const { return d->m_state; } #include "moc_audioplayer.cpp" diff --git a/core/audioplayer.h b/core/audioplayer.h index 9b28be260..ad06370b4 100644 --- a/core/audioplayer.h +++ b/core/audioplayer.h @@ -1,89 +1,88 @@ /*************************************************************************** * Copyright (C) 2007 by Pino Toscano * * * * 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. * ***************************************************************************/ #ifndef _OKULAR_AUDIOPLAYER_H_ #define _OKULAR_AUDIOPLAYER_H_ #include "okularcore_export.h" #include namespace Okular { class AudioPlayerPrivate; class Document; class Sound; class SoundAction; /** * @short An audio player. * * Singleton utility class to play sounds in documents using the KDE sound * system. */ class OKULARCORE_EXPORT AudioPlayer : public QObject { Q_OBJECT public: /** * The state of AudioPlayer * @since 0.19 (KDE 4.13) */ enum State { /** * The AudioPlayer is playing a audio file. */ PlayingState, /** * The AudioPlayer isn't playing a audio file. */ StoppedState }; ~AudioPlayer(); /** * Gets the instance of the audio player. */ static AudioPlayer * instance(); /** * Enqueue the specified @p sound for playing, optionally taking more * information about the playing from the @p soundlink . */ void playSound( const Sound * sound, const SoundAction * linksound = nullptr ); /** * Tell the AudioPlayer to stop all the playbacks. */ void stopPlaybacks(); /** * Return state of sound (playing/stopped) * @since 0.19 (KDE 4.13) */ State state() const; private: AudioPlayer(); friend class AudioPlayerPrivate; AudioPlayerPrivate * const d; friend class Document; Q_DISABLE_COPY( AudioPlayer ) - Q_PRIVATE_SLOT( d, void finished( int ) ) }; } #endif diff --git a/core/audioplayer_p.h b/core/audioplayer_p.h index 1991ca33b..53fd2896d 100644 --- a/core/audioplayer_p.h +++ b/core/audioplayer_p.h @@ -1,49 +1,46 @@ /*************************************************************************** * Copyright (C) 2007 by Pino Toscano * * * * 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. * ***************************************************************************/ #ifndef _OKULAR_AUDIOPLAYER_P_H_ #define _OKULAR_AUDIOPLAYER_P_H_ // qt/kde includes #include -#include #include class PlayData; class SoundInfo; namespace Okular { class AudioPlayer; class AudioPlayerPrivate { public: explicit AudioPlayerPrivate( AudioPlayer * qq ); ~AudioPlayerPrivate(); int newId() const; bool play( const SoundInfo& si ); void stopPlayings(); - // private slots void finished( int ); AudioPlayer * q; QHash< int, PlayData * > m_playing; - QSignalMapper m_mapper; QUrl m_currentDocument; AudioPlayer::State m_state; }; } #endif