First version of an audio player for okular, able to play the sounds in the documents.

At the moment is quite simple and works only for external sounds.
Activate the sound playing when processing links and when switching pages in presentation mode only.

svn path=/trunk/playground/graphics/okular/; revision=630315
remotes/origin/KDE/4.0
Pino Toscano 19 years ago
parent e158d82848
commit 1e7cb0b2eb
  1. 3
      CMakeLists.txt
  2. 235
      core/audioplayer.cpp
  3. 58
      core/audioplayer.h
  4. 9
      core/document.cpp
  5. 7
      ui/presentationwidget.cpp

@ -31,6 +31,7 @@ include_directories(
set(okularcore_SRCS
core/annotations.cpp
core/area.cpp
core/audioplayer.cpp
core/bookmarkmanager.cpp
core/chooseenginedialog.cpp
core/document.cpp
@ -87,7 +88,7 @@ IF(APPLE)
SET(OKULAR_IOKIT "-framework IOKit" CACHE STRING "Apple IOKit framework")
ENDIF(APPLE)
target_link_libraries(okularcore ${OKULAR_IOKIT} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBRARY} ${KDE4_KDEPRINT_LIBS} m )
target_link_libraries(okularcore ${OKULAR_IOKIT} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBRARY} ${KDE4_KDEPRINT_LIBS} ${KDE4_PHONONCORE_LIBRARY} m )
install(TARGETS okularcore DESTINATION ${LIB_INSTALL_DIR} )

@ -0,0 +1,235 @@
/***************************************************************************
* Copyright (C) 2007 by Pino Toscano <pino@kde.org> *
* *
* 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. *
***************************************************************************/
// qt/kde includes
#include <qhash.h>
#include <qsignalmapper.h>
#include <kdebug.h>
#include <krandom.h>
#include <phonon/audiopath.h>
#include <phonon/audiooutput.h>
#include <phonon/bytestream.h>
#include <phonon/mediaobject.h>
// local includes
#include "audioplayer.h"
#include "link.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 = 0, const LinkSound * ls = 0 )
: 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 PlayInfo
{
public:
PlayInfo()
: m_mediaobject( 0 ), m_bytestream( 0 ), m_path( 0 ), m_output( 0 )
{
}
~PlayInfo()
{
if ( m_bytestream )
{
m_bytestream->stop();
delete m_bytestream;
}
if ( m_mediaobject )
{
m_mediaobject->stop();
delete m_mediaobject;
}
delete m_path;
delete m_output;
}
Phonon::MediaObject * m_mediaobject;
Phonon::ByteStream * m_bytestream;
Phonon::AudioPath * m_path;
Phonon::AudioOutput * m_output;
SoundInfo m_info;
};
class AudioPlayer::Private
{
public:
Private( AudioPlayer * qq )
: q( qq )
{
connect( &m_mapper, SIGNAL( mapped( int ) ), q, SLOT( finished( int ) ) );
}
~Private()
{
qDeleteAll( m_playing );
}
int newId() const;
bool play( const SoundInfo& si );
// private slots
void finished( int );
AudioPlayer * q;
QHash< int, PlayInfo * > m_playing;
QSignalMapper m_mapper;
};
int AudioPlayer::Private::newId() const
{
int newid = 0;
QHash< int, PlayInfo * >::const_iterator it;
QHash< int, PlayInfo * >::const_iterator itEnd = m_playing.constEnd();
do
{
newid = KRandom::random();
it = m_playing.constFind( newid );
} while ( it != itEnd );
return newid;
}
bool AudioPlayer::Private::play( const SoundInfo& si )
{
kDebug() << k_funcinfo << endl;
PlayInfo * info = new PlayInfo();
info->m_output = new Phonon::AudioOutput( Phonon::NotificationCategory );
info->m_output->setVolume( si.volume );
info->m_path = new Phonon::AudioPath();
info->m_path->addOutput( info->m_output );
info->m_info = si;
bool valid = false;
switch ( si.sound->soundType() )
{
case Sound::External:
{
QString url = si.sound->url();
kDebug() << "[AudioPlayer::Playinfo::play()] External, " << url << endl;
if ( !url.isEmpty() )
{
info->m_mediaobject = new Phonon::MediaObject();
if ( info->m_mediaobject->addAudioPath( info->m_path ) )
{
QObject::connect( info->m_mediaobject, SIGNAL( finished() ), &m_mapper, SLOT( map() ) );
int newid = newId();
m_mapper.setMapping( info->m_mediaobject, newid );
info->m_mediaobject->setUrl( url );
m_playing.insert( newid, info );
valid = true;
info->m_mediaobject->play();
kDebug() << "[AudioPlayer::Playinfo::play()] PLAY url" << endl;
}
}
break;
}
case Sound::Embedded:
{
#if 0 // disable because of broken bytestream in xine :(
QByteArray data = si.sound->data();
kDebug() << "[AudioPlayer::Playinfo::play()] Embedded, " << data.length() << endl;
if ( !data.isEmpty() )
{
kDebug() << "[AudioPlayer::Playinfo::play()] bytestream: " << info->m_bytestream << endl;
info->m_bytestream = new Phonon::ByteStream();
kDebug() << "[AudioPlayer::Playinfo::play()] bytestream: " << info->m_bytestream << endl;
if ( info->m_bytestream->addAudioPath( info->m_path ) )
{
QObject::connect( info->m_bytestream, SIGNAL( finished() ), &m_mapper, SLOT( map() ) );
int newid = newId();
m_mapper.setMapping( info->m_mediaobject, newid );
m_playing.insert( newid, info );
info->m_bytestream->writeData( data );
info->m_bytestream->setStreamSize( data.length() );
info->m_bytestream->setStreamSeekable( true );
info->m_bytestream->endOfData();
valid = true;
info->m_bytestream->play();
kDebug() << "[AudioPlayer::Playinfo::play()] PLAY data" << endl;
}
}
#endif
break;
}
}
if ( !valid )
{
delete info;
info = 0;
}
return valid;
}
void AudioPlayer::Private::finished( int id )
{
QHash< int, PlayInfo * >::iterator it = m_playing.find( id );
if ( it == m_playing.end() )
return;
delete it.value();
m_playing.erase( it );
kDebug() << k_funcinfo << "finished, " << m_playing.count() << endl;
}
AudioPlayer::AudioPlayer()
: QObject(), d( new Private( this ) )
{
}
AudioPlayer::~AudioPlayer()
{
delete d;
}
AudioPlayer * AudioPlayer::instance()
{
static AudioPlayer ap;
return &ap;
}
void AudioPlayer::playSound( const Sound * sound, const LinkSound * linksound )
{
// we can't play null pointers ;)
if ( !sound )
return;
kDebug() << k_funcinfo << endl;
SoundInfo si( sound, linksound );
d->play( si );
}
#include "audioplayer.moc"

@ -0,0 +1,58 @@
/***************************************************************************
* Copyright (C) 2007 by Pino Toscano <pino@kde.org> *
* *
* 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 <core/okular_export.h>
#include <QtCore/QObject>
namespace Okular {
class LinkSound;
class Sound;
/**
* @short An audio player.
*
* Singleton utility class to play sounds in documents using the KDE sound
* system.
*/
class OKULAR_EXPORT AudioPlayer : public QObject
{
Q_OBJECT
public:
~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 LinkSound * linksound = 0 );
private:
AudioPlayer();
class Private;
Private * const d;
Q_DISABLE_COPY( AudioPlayer )
Q_PRIVATE_SLOT( d, void finished( int ) )
};
}
#endif

@ -33,6 +33,7 @@
#include <ktoolinvocation.h>
// local includes
#include "audioplayer.h"
#include "bookmarkmanager.h"
#include "chooseenginedialog.h"
#include "document.h"
@ -2033,13 +2034,15 @@ void Document::processLink( const Link * link )
}
} break;
case Link::Sound: {
const LinkSound * linksound = static_cast< const LinkSound * >( link );
AudioPlayer::instance()->playSound( linksound->sound(), linksound );
} break;
case Link::Movie:
//const LinkMovie * browse = static_cast< const LinkMovie * >( link );
// TODO this (Movie link)
break;
case Link::Sound:
// TODO this (Sound link)
break;
}
}

@ -622,9 +622,16 @@ void PresentationWidget::changePage( int newPage )
// set a new viewport in document if page number differs
if ( m_frameIndex != -1 && m_frameIndex != m_document->viewport().pageNumber )
{
if ( m_document->page( m_document->viewport().pageNumber )->pageAction( Okular::Page::Closing ) )
m_document->processLink( m_document->page( m_document->viewport().pageNumber )->pageAction( Okular::Page::Closing ) );
// remove the drawing on the old page before switching
clearDrawings();
m_document->setViewportPage( m_frameIndex, PRESENTATION_ID );
if ( m_document->page( m_frameIndex)->pageAction( Okular::Page::Opening ) )
m_document->processLink( m_document->page( m_frameIndex )->pageAction( Okular::Page::Opening ) );
}
}

Loading…
Cancel
Save