okular
audioplayer.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "audioplayer.h"
00011 #include "audioplayer_p.h"
00012
00013
00014 #include <qbuffer.h>
00015 #include <qdir.h>
00016 #include <kdebug.h>
00017 #include <krandom.h>
00018 #include <Phonon/Path>
00019 #include <phonon/audiooutput.h>
00020 #include <phonon/abstractmediastream.h>
00021 #include <phonon/mediaobject.h>
00022
00023
00024 #include "action.h"
00025 #include "debug_p.h"
00026 #include "sound.h"
00027
00028 using namespace Okular;
00029
00030
00031 class SoundInfo
00032 {
00033 public:
00034 explicit SoundInfo( const Sound * s = 0, const SoundAction * ls = 0 )
00035 : sound( s ), volume( 0.5 ), synchronous( false ), repeat( false ),
00036 mix( false )
00037 {
00038 if ( ls )
00039 {
00040 volume = ls->volume();
00041 synchronous = ls->synchronous();
00042 repeat = ls->repeat();
00043 mix = ls->mix();
00044 }
00045 }
00046
00047 const Sound * sound;
00048 double volume;
00049 bool synchronous;
00050 bool repeat;
00051 bool mix;
00052 };
00053
00054
00055 class PlayData
00056 {
00057 public:
00058 PlayData()
00059 : m_mediaobject( 0 ), m_output( 0 ), m_buffer( 0 )
00060 {
00061 }
00062
00063 void play()
00064 {
00065 if ( m_buffer )
00066 {
00067 m_buffer->open( QIODevice::ReadOnly );
00068 }
00069 m_mediaobject->play();
00070 }
00071
00072 ~PlayData()
00073 {
00074 m_mediaobject->stop();
00075 delete m_mediaobject;
00076 delete m_output;
00077 delete m_buffer;
00078 }
00079
00080 Phonon::MediaObject * m_mediaobject;
00081 Phonon::AudioOutput * m_output;
00082 QBuffer * m_buffer;
00083 SoundInfo m_info;
00084 };
00085
00086
00087 AudioPlayerPrivate::AudioPlayerPrivate( AudioPlayer * qq )
00088 : q( qq )
00089 {
00090 QObject::connect( &m_mapper, SIGNAL( mapped( int ) ), q, SLOT( finished( int ) ) );
00091 }
00092
00093 AudioPlayerPrivate::~AudioPlayerPrivate()
00094 {
00095 stopPlayings();
00096 }
00097
00098 int AudioPlayerPrivate::newId() const
00099 {
00100 int newid = 0;
00101 QHash< int, PlayData * >::const_iterator it;
00102 QHash< int, PlayData * >::const_iterator itEnd = m_playing.constEnd();
00103 do
00104 {
00105 newid = KRandom::random();
00106 it = m_playing.constFind( newid );
00107 } while ( it != itEnd );
00108 return newid;
00109 }
00110
00111 bool AudioPlayerPrivate::play( const SoundInfo& si )
00112 {
00113 kDebug() ;
00114 PlayData * data = new PlayData();
00115 data->m_output = new Phonon::AudioOutput( Phonon::NotificationCategory );
00116 data->m_output->setVolume( si.volume );
00117 data->m_mediaobject = new Phonon::MediaObject();
00118 Phonon::createPath(data->m_mediaobject, data->m_output);
00119 data->m_info = si;
00120 bool valid = false;
00121
00122 switch ( si.sound->soundType() )
00123 {
00124 case Sound::External:
00125 {
00126 QString url = si.sound->url();
00127 kDebug(OkularDebug) << "External," << url;
00128 if ( !url.isEmpty() )
00129 {
00130 int newid = newId();
00131 m_mapper.setMapping( data->m_mediaobject, newid );
00132 KUrl newurl;
00133 if ( KUrl::isRelativeUrl( url ) )
00134 {
00135 newurl = m_currentDocument;
00136 newurl.setFileName( url );
00137 }
00138 else
00139 {
00140 newurl = url;
00141 }
00142 data->m_mediaobject->setCurrentSource( newurl );
00143 m_playing.insert( newid, data );
00144 valid = true;
00145 }
00146 break;
00147 }
00148 case Sound::Embedded:
00149 {
00150 QByteArray filedata = si.sound->data();
00151 kDebug(OkularDebug) << "Embedded," << filedata.length();
00152 if ( !filedata.isEmpty() )
00153 {
00154 kDebug(OkularDebug) << "Mediaobject:" << data->m_mediaobject;
00155 int newid = newId();
00156 m_mapper.setMapping( data->m_mediaobject, newid );
00157 data->m_buffer = new QBuffer();
00158 data->m_buffer->setData( filedata );
00159 data->m_mediaobject->setCurrentSource( Phonon::MediaSource( data->m_buffer ) );
00160 m_playing.insert( newid, data );
00161 valid = true;
00162 }
00163 break;
00164 }
00165 }
00166 if ( !valid )
00167 {
00168 delete data;
00169 data = 0;
00170 }
00171 if ( data )
00172 {
00173 QObject::connect( data->m_mediaobject, SIGNAL( finished() ), &m_mapper, SLOT( map() ) );
00174 kDebug(OkularDebug) << "PLAY";
00175 data->play();
00176 }
00177 return valid;
00178 }
00179
00180 void AudioPlayerPrivate::stopPlayings()
00181 {
00182 qDeleteAll( m_playing );
00183 m_playing.clear();
00184 }
00185
00186 void AudioPlayerPrivate::finished( int id )
00187 {
00188 QHash< int, PlayData * >::iterator it = m_playing.find( id );
00189 if ( it == m_playing.end() )
00190 return;
00191
00192 SoundInfo si = it.value()->m_info;
00193
00194
00195 if ( si.repeat )
00196 {
00197 it.value()->play();
00198 }
00199 else
00200 {
00201 delete it.value();
00202 m_playing.erase( it );
00203 }
00204 kDebug(OkularDebug) << "finished," << m_playing.count();
00205 }
00206
00207
00208 AudioPlayer::AudioPlayer()
00209 : QObject(), d( new AudioPlayerPrivate( this ) )
00210 {
00211 }
00212
00213 AudioPlayer::~AudioPlayer()
00214 {
00215 delete d;
00216 }
00217
00218 AudioPlayer * AudioPlayer::instance()
00219 {
00220 static AudioPlayer ap;
00221 return ≈
00222 }
00223
00224 void AudioPlayer::playSound( const Sound * sound, const SoundAction * linksound )
00225 {
00226
00227 if ( !sound )
00228 return;
00229
00230
00231 if ( sound->soundType() == Sound::External && !d->m_currentDocument.isLocalFile() )
00232 return;
00233
00234 kDebug() ;
00235 SoundInfo si( sound, linksound );
00236
00237
00238
00239 if ( !si.mix )
00240 d->stopPlayings();
00241
00242 d->play( si );
00243 }
00244
00245 void AudioPlayer::stopPlaybacks()
00246 {
00247 d->stopPlayings();
00248 }
00249
00250 #include "audioplayer.moc"