compile
[kdegraphics.git] / okular / core / audioplayer.cpp
blobd1d841c76e0ab1f107b16bd1014dd4cab854ddc3
1 /***************************************************************************
2 * Copyright (C) 2007 by Pino Toscano <pino@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "audioplayer.h"
11 #include "audioplayer_p.h"
13 // qt/kde includes
14 #include <qbuffer.h>
15 #include <qdir.h>
16 #include <kdebug.h>
17 #include <krandom.h>
18 #include <Phonon/Path>
19 #include <phonon/audiooutput.h>
20 #include <phonon/abstractmediastream.h>
21 #include <phonon/mediaobject.h>
23 // local includes
24 #include "action.h"
25 #include "debug_p.h"
26 #include "sound.h"
28 using namespace Okular;
30 // helper class used to store info about a sound to be played
31 class SoundInfo
33 public:
34 explicit SoundInfo( const Sound * s = 0, const SoundAction * ls = 0 )
35 : sound( s ), volume( 0.5 ), synchronous( false ), repeat( false ),
36 mix( false )
38 if ( ls )
40 volume = ls->volume();
41 synchronous = ls->synchronous();
42 repeat = ls->repeat();
43 mix = ls->mix();
47 const Sound * sound;
48 double volume;
49 bool synchronous;
50 bool repeat;
51 bool mix;
55 class PlayData
57 public:
58 PlayData()
59 : m_mediaobject( 0 ), m_output( 0 ), m_buffer( 0 )
63 void play()
65 if ( m_buffer )
67 m_buffer->open( QIODevice::ReadOnly );
69 m_mediaobject->play();
72 ~PlayData()
74 m_mediaobject->stop();
75 delete m_mediaobject;
76 delete m_output;
77 delete m_buffer;
80 Phonon::MediaObject * m_mediaobject;
81 Phonon::AudioOutput * m_output;
82 QBuffer * m_buffer;
83 SoundInfo m_info;
87 AudioPlayerPrivate::AudioPlayerPrivate( AudioPlayer * qq )
88 : q( qq )
90 QObject::connect( &m_mapper, SIGNAL( mapped( int ) ), q, SLOT( finished( int ) ) );
93 AudioPlayerPrivate::~AudioPlayerPrivate()
95 stopPlayings();
98 int AudioPlayerPrivate::newId() const
100 int newid = 0;
101 QHash< int, PlayData * >::const_iterator it;
102 QHash< int, PlayData * >::const_iterator itEnd = m_playing.constEnd();
105 newid = KRandom::random();
106 it = m_playing.constFind( newid );
107 } while ( it != itEnd );
108 return newid;
111 bool AudioPlayerPrivate::play( const SoundInfo& si )
113 kDebug() ;
114 PlayData * data = new PlayData();
115 data->m_output = new Phonon::AudioOutput( Phonon::NotificationCategory );
116 data->m_output->setVolume( si.volume );
117 data->m_mediaobject = new Phonon::MediaObject();
118 Phonon::createPath(data->m_mediaobject, data->m_output);
119 data->m_info = si;
120 bool valid = false;
122 switch ( si.sound->soundType() )
124 case Sound::External:
126 QString url = si.sound->url();
127 kDebug(OkularDebug) << "External," << url;
128 if ( !url.isEmpty() )
130 int newid = newId();
131 m_mapper.setMapping( data->m_mediaobject, newid );
132 KUrl newurl;
133 if ( KUrl::isRelativeUrl( url ) )
135 newurl = m_currentDocument;
136 newurl.setFileName( url );
138 else
140 newurl = url;
142 data->m_mediaobject->setCurrentSource( newurl );
143 m_playing.insert( newid, data );
144 valid = true;
146 break;
148 case Sound::Embedded:
150 QByteArray filedata = si.sound->data();
151 kDebug(OkularDebug) << "Embedded," << filedata.length();
152 if ( !filedata.isEmpty() )
154 kDebug(OkularDebug) << "Mediaobject:" << data->m_mediaobject;
155 int newid = newId();
156 m_mapper.setMapping( data->m_mediaobject, newid );
157 data->m_buffer = new QBuffer();
158 data->m_buffer->setData( filedata );
159 data->m_mediaobject->setCurrentSource( Phonon::MediaSource( data->m_buffer ) );
160 m_playing.insert( newid, data );
161 valid = true;
163 break;
166 if ( !valid )
168 delete data;
169 data = 0;
171 if ( data )
173 QObject::connect( data->m_mediaobject, SIGNAL( finished() ), &m_mapper, SLOT( map() ) );
174 kDebug(OkularDebug) << "PLAY";
175 data->play();
177 return valid;
180 void AudioPlayerPrivate::stopPlayings()
182 qDeleteAll( m_playing );
183 m_playing.clear();
186 void AudioPlayerPrivate::finished( int id )
188 QHash< int, PlayData * >::iterator it = m_playing.find( id );
189 if ( it == m_playing.end() )
190 return;
192 SoundInfo si = it.value()->m_info;
193 // if the sound must be repeated indefinitely, then start the playback
194 // again, otherwise destroy the PlayData as it's no more useful
195 if ( si.repeat )
197 it.value()->play();
199 else
201 delete it.value();
202 m_playing.erase( it );
204 kDebug(OkularDebug) << "finished," << m_playing.count();
208 AudioPlayer::AudioPlayer()
209 : QObject(), d( new AudioPlayerPrivate( this ) )
213 AudioPlayer::~AudioPlayer()
215 delete d;
218 AudioPlayer * AudioPlayer::instance()
220 static AudioPlayer ap;
221 return &ap;
224 void AudioPlayer::playSound( const Sound * sound, const SoundAction * linksound )
226 // we can't play null pointers ;)
227 if ( !sound )
228 return;
230 // we don't play external sounds for remote documents
231 if ( sound->soundType() == Sound::External && !d->m_currentDocument.isLocalFile() )
232 return;
234 kDebug() ;
235 SoundInfo si( sound, linksound );
237 // if the mix flag of the new sound is false, then the currently playing
238 // sounds must be stopped.
239 if ( !si.mix )
240 d->stopPlayings();
242 d->play( si );
245 void AudioPlayer::stopPlaybacks()
247 d->stopPlayings();
250 #include "audioplayer.moc"