Commit 42c016c6 authored by Albert Astals Cid's avatar Albert Astals Cid

* poppler/Link.cc:

        * poppler/Link.h:
        * poppler/Makefile.am:
        * poppler/Page.cc:
        * poppler/Page.h:
        * poppler/Sound.cc:
        * poppler/Sound.h: Make poppler able to read Sound objects, Sound
        actions and Opening/Closing page actions. Patch by Pino Toscano.

        * qt4/src/Makefile.am:
        * qt4/src/poppler-link.cc:
        * qt4/src/poppler-link.h:
        * qt4/src/poppler-qt4.h:
        * qt4/src/poppler-page.cc:
        * qt4/src/poppler-sound.cc: Support for sounds, sound links and page
        actions in the Qt4 backend. Patch by Pino Toscano.
parent 1da064d7
2006-10-08 Albert Astals Cid <aacid@kde.org>
* poppler/Link.cc:
* poppler/Link.h:
* poppler/Makefile.am:
* poppler/Page.cc:
* poppler/Page.h:
* poppler/Sound.cc:
* poppler/Sound.h: Make poppler able to read Sound objects, Sound
actions and Opening/Closing page actions. Patch by Pino Toscano.
* qt4/src/Makefile.am:
* qt4/src/poppler-link.cc:
* qt4/src/poppler-link.h:
* qt4/src/poppler-qt4.h:
* qt4/src/poppler-page.cc:
* qt4/src/poppler-sound.cc: Support for sounds, sound links and page
actions in the Qt4 backend. Patch by Pino Toscano.
2006-09-30 Albert Astals Cid <aacid@kde.org>
* qt4/src/poppler-page.cc: PA is optional, H is a name not a string
......
......@@ -21,6 +21,7 @@
#include "Array.h"
#include "Dict.h"
#include "Link.h"
#include "Sound.h"
#include "UGooString.h"
//------------------------------------------------------------------------
......@@ -88,6 +89,10 @@ LinkAction *LinkAction::parseAction(Object *obj, GooString *baseURI) {
obj3.free();
obj4.free();
// Sound action
} else if (obj2.isName("Sound")) {
action = new LinkSound(obj);
// unknown action
} else if (obj2.isName()) {
action = new LinkUnknown(obj2.getName());
......@@ -625,6 +630,54 @@ LinkMovie::~LinkMovie() {
}
}
//------------------------------------------------------------------------
// LinkSound
//------------------------------------------------------------------------
LinkSound::LinkSound(Object *soundObj) {
volume = 1.0;
sync = gFalse;
repeat = gFalse;
mix = gFalse;
sound = NULL;
if (soundObj->isDict())
{
Object tmp;
// volume
soundObj->dictLookup("Volume", &tmp);
if (tmp.isNum()) {
volume = tmp.getNum();
}
tmp.free();
// sync
soundObj->dictLookup("Synchronous", &tmp);
if (tmp.isBool()) {
sync = tmp.getBool();
}
tmp.free();
// repeat
soundObj->dictLookup("Repeat", &tmp);
if (tmp.isBool()) {
repeat = tmp.getBool();
}
tmp.free();
// mix
soundObj->dictLookup("Mix", &tmp);
if (tmp.isBool()) {
mix = tmp.getBool();
}
tmp.free();
// 'Sound' object
soundObj->dictLookup("Sound", &tmp);
sound = Sound::parseSound(&tmp);
tmp.free();
}
}
LinkSound::~LinkSound() {
delete sound;
}
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
......
......@@ -19,6 +19,7 @@ class GooString;
class UGooString;
class Array;
class Dict;
class Sound;
//------------------------------------------------------------------------
// LinkAction
......@@ -31,6 +32,7 @@ enum LinkActionKind {
actionURI, // URI
actionNamed, // named action
actionMovie, // movie action
actionSound, // sound action
actionUnknown // anything else
};
......@@ -275,6 +277,36 @@ private:
GooString *title;
};
//------------------------------------------------------------------------
// LinkSound
//------------------------------------------------------------------------
class LinkSound: public LinkAction {
public:
LinkSound(Object *soundObj);
virtual ~LinkSound();
virtual GBool isOk() { return sound != NULL; }
virtual LinkActionKind getKind() { return actionSound; }
double getVolume() { return volume; }
GBool getSynchronous() { return sync; }
GBool getRepeat() { return repeat; }
GBool getMix() { return mix; }
Sound *getSound() { return sound; }
private:
double volume;
GBool sync;
GBool repeat;
GBool mix;
Sound *sound;
};
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
......
......@@ -156,6 +156,7 @@ poppler_include_HEADERS = \
UGooString.h \
UTF8.h \
XpdfPluginAPI.h \
Sound.h \
poppler-config.h
endif
......@@ -208,6 +209,7 @@ libpoppler_la_SOURCES = \
PageLabelInfo.cc \
SecurityHandler.cc \
UGooString.cc \
Sound.cc \
XpdfPluginAPI.cc
EXTRA_DIST = gen-unicode-tables.py
......@@ -230,6 +230,14 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
num, thumb.getTypeName());
thumb.initNull();
}
// actions
pageDict->lookupNF("AA", &actions);
if (!(actions.isDict() || actions.isNull())) {
error(-1, "Page additional action object (page %d) is wrong type (%s)",
num, actions.getTypeName());
actions.initNull();
}
return;
......
......@@ -151,6 +151,9 @@ public:
// Get transition.
Object *getTrans(Object *obj) { return trans.fetch(xref, obj); }
// Get actions
Object *getActions(Object *obj) { return actions.fetch(xref, obj); }
Gfx *createGfx(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop,
int sliceX, int sliceY, int sliceW, int sliceH,
......@@ -194,6 +197,7 @@ private:
Object contents; // page contents
Object thumb; // page thumbnail
Object trans; // page transition
Object actions; // page addiction actions
GBool ok; // true if page is valid
};
......
/* Sound.cc - an object that holds the sound structure
* Copyright (C) 2006, 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, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "GooString.h"
#include "Object.h"
#include "Sound.h"
#include "Stream.h"
Sound *Sound::parseSound(Object *obj)
{
// let's try to see if this Object is a Sound, according to the PDF specs
// (section 9.2)
Stream *str = NULL;
// the Object must be a Stream
if (obj->isStream()) {
str = obj->getStream();
} else {
return NULL;
}
// the Stream must have a Dict
Dict *dict = str->getDict();
if (dict == NULL)
return NULL;
Object tmp;
// the Dict must have the 'R' key of type num
dict->lookup("R", &tmp);
if (tmp.isNum()) {
return new Sound(obj);
} else {
return NULL;
}
}
Sound::Sound(Object *obj)
{
streamObj = new Object();
streamObj->initNull();
obj->copy(streamObj);
}
Sound::~Sound()
{
streamObj->free();
}
Stream *Sound::getStream()
{
return streamObj->getStream();
}
/* Sound.h - an object that holds the sound structure
* Copyright (C) 2006, 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, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef Sound_H
#define Sound_H
class Object;
class Stream;
//------------------------------------------------------------------------
class Sound
{
public:
// Try to parse the Object s
static Sound *parseSound(Object *s);
// Destructor
~Sound();
Object *getObject() { return streamObj; }
Stream *getStream();
private:
// Create a sound. The Object obj is ensured to be a Stream with a Dict
Sound(Object *obj);
Object *streamObj;
};
#endif
......@@ -25,6 +25,7 @@ libpoppler_qt4_la_SOURCES = \
poppler-link.cc \
poppler-annotation.cc \
../../qt/poppler-page-transition.cc \
poppler-sound.cc \
poppler-annotation-helper.h \
poppler-private.h
......
......@@ -247,6 +247,41 @@ namespace Poppler {
return Action;
}
// LinkSound
LinkSound::LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound ) : Link(linkArea), m_volume(volume), m_sync(sync), m_repeat(repeat), m_mix(mix), m_sound(sound)
{
}
Link::LinkType LinkSound::linkType() const
{
return Sound;
}
double LinkSound::volume() const
{
return m_volume;
}
bool LinkSound::synchronous() const
{
return m_sync;
}
bool LinkSound::repeat() const
{
return m_repeat;
}
bool LinkSound::mix() const
{
return m_mix;
}
SoundObject *LinkSound::sound() const
{
return m_sound;
}
// LinkMovie
LinkMovie::LinkMovie( const QRectF &linkArea ) : Link(linkArea)
{
......
......@@ -27,6 +27,7 @@
namespace Poppler {
class LinkDestinationData;
class SoundObject;
class LinkDestination
{
......@@ -83,7 +84,7 @@ class Link
Link( const QRectF &linkArea );
// get link type (inherited classes mustreturn an unique identifier)
enum LinkType { None, Goto, Execute, Browse, Action, Movie };
enum LinkType { None, Goto, Execute, Browse, Action, Sound, Movie };
virtual LinkType linkType() const;
// virtual destructor
......@@ -174,6 +175,29 @@ class LinkAction : public Link
ActionType m_type;
};
/** Sound: a sound to be played **/
class LinkSound : public Link
{
public:
// create a Link_Sound
LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound );
LinkType linkType() const;
double volume() const;
bool synchronous() const;
bool repeat() const;
bool mix() const;
SoundObject *sound() const;
private:
double m_volume;
bool m_sync;
bool m_repeat;
bool m_mix;
SoundObject *m_sound;
};
/** Movie: Not yet defined -> think renaming to 'Media' link **/
class LinkMovie : public Link
// TODO this (Movie link)
......
......@@ -123,6 +123,12 @@ Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea
}
break;
case actionSound:
{
::LinkSound *ls = (::LinkSound *)a;
popplerLink = new LinkSound( linkArea, ls->getVolume(), ls->getSynchronous(), ls->getRepeat(), ls->getMix(), new SoundObject( ls->getSound() ) );
}
case actionMovie:
/* TODO this (Movie link)
m_type = Movie;
......@@ -366,6 +372,32 @@ PageTransition *Page::transition() const
return m_page->transition;
}
Link *Page::action( PageAction act ) const
{
if ( act == Page::Opening || act == Page::Closing )
{
::Page *p = m_page->parentDoc->m_doc->doc.getCatalog()->getPage(m_page->index + 1);
Object o;
p->getActions(&o);
if (!o.isDict())
{
o.free();
return 0;
}
Dict *dict = o.getDict();
Object o2;
const char *key = act == Page::Opening ? "O" : "C";
dict->lookup(key, &o2);
::LinkAction *act = ::LinkAction::parseAction(&o2, m_page->parentDoc->m_doc->doc.getCatalog()->getBaseURI() );
o2.free();
Link *popplerLink = NULL;
if (act != NULL)
popplerLink = m_page->convertLinkActionToLink(act, QRectF(), m_page->parentDoc->m_doc);
return popplerLink;
}
return 0;
}
QSizeF Page::pageSizeF() const
{
::Page *p;
......
......@@ -33,6 +33,7 @@
#include <poppler-page-transition.h>
class EmbFile;
class Sound;
/**
The Poppler Qt bindings
......@@ -224,6 +225,14 @@ namespace Poppler {
enum Rotation { Rotate0 = 0, Rotate90 = 1, Rotate180 = 2, Rotate270 = 3 };
/**
The kinds of page actions
*/
enum PageAction {
Opening, ///< The action when a page is "opened"
Closing ///< The action when a page is "closed"
};
/**
Render the page to a QImage using the Splash renderer
......@@ -375,6 +384,11 @@ delete pixmap;
**/
PageTransition *transition() const;
/**
Gets the page action specified, or NULL if there is no action
**/
Link *action( PageAction act ) const;
/**
Types of orientations that are possible
*/
......@@ -710,6 +724,79 @@ delete pixmap;
*/
QDateTime convertDate( char *dateString );
class SoundData;
/**
Container class for a sound file in a PDF document.
A sound can be either External (in that case should be loaded the file
whose url is represented by url() ), or Embedded, and the player has to
play the data contained in data().
*/
class SoundObject {
public:
/**
The type of sound
*/
enum SoundType {
External, ///< The real sound file is external
Embedded ///< The sound is contained in the data
};
/**
The encoding format used for the sound
*/
enum SoundEncoding {
Raw, ///< Raw encoding, with unspecified or unsigned values in the range [ 0, 2^B − 1 ]
Signed, ///< Twos-complement values
muLaw, ///< mu-law-encoded samples
ALaw ///< A-law-encoded samples
};
SoundObject(Sound *popplersound);
SoundObject(const SoundObject &s);
~SoundObject();
/**
Is the sound embedded (@ref Embedded ) or external (@ref External )?
*/
SoundType soundType() const;
/**
The URL of the sound file to be played, in case of @ref External
*/
QString url() const;
/**
The data of the sound, in case of @ref Embedded
*/
QByteArray data() const;
/**
The sampling rate of the sound
*/
double samplingRate() const;
/**
The number of sound channels to use to play the sound
*/
int channels() const;
/**
The number of bits per sample value per channel
*/
int bitsPerSample() const;
/**
The encoding used for the sound
*/
SoundEncoding soundEncoding() const;
private:
SoundData *m_soundData;
};
}
#endif
......
/* poppler-sound.cc: qt interface to poppler
* Copyright (C) 2006, 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, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define UNSTABLE_POPPLER_QT4
#include <QtCore/QByteArray>
#include <QtCore/QString>
#include <QtCore/QVariant>
#include "Object.h"
#include "Dict.h"
#include "Stream.h"
#include "Sound.h"
#include "poppler-qt4.h"
namespace Poppler
{
class SoundData
{
public:
SoundData()
: m_channels( 1 ), m_bitsPerSample( 8 ), m_soundEncoding( SoundObject::Raw ), m_soundObj( new Object() )
{ m_soundObj->initNull(); }
QVariant m_data;
SoundObject::SoundType m_type;
double m_samplingRate;
int m_channels;
int m_bitsPerSample;
SoundObject::SoundEncoding m_soundEncoding;
Object *m_soundObj;
};
SoundObject::SoundObject(Sound *popplersound)
{
m_soundData = new SoundData();
Dict *dict = popplersound->getStream()->getDict();
Object tmp;
// file specs / data
dict->lookup("F", &tmp);
if ( !tmp.isNull() )
{
// valid 'F' key -> external file
m_soundData->m_type = SoundObject::External;
// TODO read the file specifications
m_soundData->m_data = QVariant( QString() );
}
else
{
// no file specification, then the sound data have to be
// extracted from the stream
m_soundData->m_type = SoundObject::Embedded;
Stream *stream = popplersound->getStream();
stream->reset();
int dataLen = 0;
QByteArray fileArray;
int i;
while ( (i = stream->getChar()) != EOF) {
fileArray[dataLen] = (char)i;
++dataLen;
}
fileArray.resize(dataLen);
m_soundData->m_data = QVariant( fileArray );
}
tmp.free();
// sampling rate
dict->lookup( "R", &tmp );
if ( tmp.isNum() )
{
m_soundData->m_samplingRate = tmp.getNum();
}
tmp.free();
// sound channels
dict->lookup( "C", &tmp );
if ( tmp.isInt() )
{
m_soundData->m_channels = tmp.getInt();
}
tmp.free();
// sound channels
dict->lookup( "B", &tmp );
if ( tmp.isInt() )
{
m_soundData->m_bitsPerSample = tmp.getInt();
}
tmp.free();
// encoding format
dict->lookup( "E", &tmp );
if ( tmp.isName() )
{
const char *enc = tmp.getName();
if ( !strcmp( "Raw", enc ) )
m_soundData->m_soundEncoding = SoundObject::Raw;
else if ( !strcmp( "Signed", enc ) )
m_soundData->m_soundEncoding = SoundObject::Signed;
if ( !strcmp( "muLaw", enc ) )
m_soundData->m_soundEncoding = SoundObject::muLaw;
if ( !strcmp( "ALaw", enc ) )
m_soundData->m_soundEncoding = SoundObject::ALaw;
}
tmp.free();
// at the end, copying the object
popplersound->getObject()->copy(m_soundData->m_soundObj);
}
SoundObject::SoundObject(const SoundObject &s)
{
m_soundData = new SoundData();
m_soundData->m_type = s.m_soundData->m_type;
m_soundData->m_data = s.m_soundData->m_data;
m_soundData->m_type = s.m_soundData->m_type;
m_soundData->m_samplingRate = s.m_soundData->m_samplingRate;
m_soundData->m_channels = s.m_soundData->m_channels;
m_soundData->m_bitsPerSample = s.m_soundData->m_bitsPerSample;
m_soundData->m_soundEncoding = s.m_soundData->m_soundEncoding;
s.m_soundData->m_soundObj->copy(m_soundData->m_soundObj);
}
SoundObject::~SoundObject()
{
m_soundData->m_soundObj->free();
delete m_soundData;
}
SoundObject::SoundType SoundObject::soundType() const
{
return m_soundData->m_type;
}
QString SoundObject::url() const
{
return m_soundData->m_type == SoundObject::External ? m_soundData->m_data.toString() : QString();
}
QByteArray SoundObject::data() const
{
return m_soundData->m_type == SoundObject::Embedded ? m_soundData->m_data.toByteArray() : QByteArray();
};
double SoundObject::samplingRate() const
{
return m_soundData->m_samplingRate;
}
int SoundObject::channels() const
{
return m_soundData->m_channels;
}
int SoundObject::bitsPerSample() const
{
return m_soundData->m_bitsPerSample;
}
SoundObject::SoundEncoding SoundObject::soundEncoding() const
{
return m_soundData->m_soundEncoding;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment