blob: 1c185a77f6ee0d56fc8d3800c10265f09cf65dec [file] [log] [blame]
//*********************************************************************************
// Movie.cc
//---------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------
// Hugo Mercier <hmercier31[at]gmail.com> (c) 2008
// Pino Toscano <pino@kde.org> (c) 2008
// Carlos Garcia Campos <carlosgc@gnome.org> (c) 2010
// Albert Astals Cid <aacid@kde.org> (c) 2010, 2017-2019, 2022
// Evgeny Stambulchik <fnevgeny@gmail.com> (c) 2019
//
// 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.
//
// 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 <cmath>
#include "Movie.h"
#include "FileSpec.h"
MovieActivationParameters::MovieActivationParameters()
{
// default values
floatingWindow = false;
xPosition = 0.5;
yPosition = 0.5;
rate = 1.0;
volume = 100;
showControls = false;
synchronousPlay = false;
repeatMode = repeatModeOnce;
start.units = 0;
duration.units = 0;
znum = 1;
zdenum = 1;
}
MovieActivationParameters::~MovieActivationParameters() { }
void MovieActivationParameters::parseMovieActivation(const Object *aDict)
{
Object obj1 = aDict->dictLookup("Start");
if (obj1.isInt()) {
// If it is representable as an integer (subject to the implementation limit for
// integers, as described in Appendix C), it should be specified as such.
start.units = obj1.getInt();
} else if (obj1.isString()) {
// If it is not representable as an integer, it should be specified as an 8-byte
// string representing a 64-bit twos-complement integer, most significant
// byte first.
// UNSUPPORTED
} else if (obj1.isArray()) {
Array *a = obj1.getArray();
Object tmp = a->get(0);
if (tmp.isInt()) {
start.units = tmp.getInt();
}
if (tmp.isString()) {
// UNSUPPORTED
}
tmp = a->get(1);
if (tmp.isInt()) {
start.units_per_second = tmp.getInt();
}
}
obj1 = aDict->dictLookup("Duration");
if (obj1.isInt()) {
duration.units = obj1.getInt();
} else if (obj1.isString()) {
// UNSUPPORTED
} else if (obj1.isArray()) {
Array *a = obj1.getArray();
Object tmp = a->get(0);
if (tmp.isInt()) {
duration.units = tmp.getInt();
}
if (tmp.isString()) {
// UNSUPPORTED
}
tmp = a->get(1);
if (tmp.isInt()) {
duration.units_per_second = tmp.getInt();
}
}
obj1 = aDict->dictLookup("Rate");
if (obj1.isNum()) {
rate = obj1.getNum();
}
obj1 = aDict->dictLookup("Volume");
if (obj1.isNum()) {
// convert volume to [0 100]
volume = int((obj1.getNum() + 1.0) * 50);
}
obj1 = aDict->dictLookup("ShowControls");
if (obj1.isBool()) {
showControls = obj1.getBool();
}
obj1 = aDict->dictLookup("Synchronous");
if (obj1.isBool()) {
synchronousPlay = obj1.getBool();
}
obj1 = aDict->dictLookup("Mode");
if (obj1.isName()) {
const char *name = obj1.getName();
if (!strcmp(name, "Once")) {
repeatMode = repeatModeOnce;
} else if (!strcmp(name, "Open")) {
repeatMode = repeatModeOpen;
} else if (!strcmp(name, "Repeat")) {
repeatMode = repeatModeRepeat;
} else if (!strcmp(name, "Palindrome")) {
repeatMode = repeatModePalindrome;
}
}
obj1 = aDict->dictLookup("FWScale");
if (obj1.isArray()) {
// the presence of that entry implies that the movie is to be played
// in a floating window
floatingWindow = true;
Array *scale = obj1.getArray();
if (scale->getLength() >= 2) {
Object tmp = scale->get(1);
if (tmp.isInt()) {
znum = tmp.getInt();
}
tmp = scale->get(1);
if (tmp.isInt()) {
zdenum = tmp.getInt();
}
}
}
obj1 = aDict->dictLookup("FWPosition");
if (obj1.isArray()) {
Array *pos = obj1.getArray();
if (pos->getLength() >= 2) {
Object tmp = pos->get(0);
if (tmp.isNum()) {
xPosition = tmp.getNum();
}
tmp = pos->get(1);
if (tmp.isNum()) {
yPosition = tmp.getNum();
}
}
}
}
void Movie::parseMovie(const Object *movieDict)
{
fileName = nullptr;
rotationAngle = 0;
width = -1;
height = -1;
showPoster = false;
Object obj1 = movieDict->dictLookup("F");
Object obj2 = getFileSpecNameForPlatform(&obj1);
if (obj2.isString()) {
fileName = obj2.getString()->copy();
} else {
error(errSyntaxError, -1, "Invalid Movie");
ok = false;
return;
}
obj1 = movieDict->dictLookup("Aspect");
if (obj1.isArray()) {
Array *aspect = obj1.getArray();
if (aspect->getLength() >= 2) {
Object tmp = aspect->get(0);
if (tmp.isNum()) {
width = (int)floor(tmp.getNum() + 0.5);
}
tmp = aspect->get(1);
if (tmp.isNum()) {
height = (int)floor(tmp.getNum() + 0.5);
}
}
}
obj1 = movieDict->dictLookup("Rotate");
if (obj1.isInt()) {
// round up to 90°
rotationAngle = (((obj1.getInt() + 360) % 360) % 90) * 90;
}
//
// movie poster
//
poster = movieDict->dictLookupNF("Poster").copy();
if (!poster.isNull()) {
if (poster.isRef() || poster.isStream()) {
showPoster = true;
} else if (poster.isBool()) {
showPoster = poster.getBool();
poster.setToNull();
} else {
poster.setToNull();
}
}
}
Movie::~Movie()
{
delete fileName;
}
Movie::Movie(const Object *movieDict)
{
ok = true;
if (movieDict->isDict()) {
parseMovie(movieDict);
} else {
ok = false;
}
}
Movie::Movie(const Object *movieDict, const Object *aDict)
{
ok = true;
if (movieDict->isDict()) {
parseMovie(movieDict);
if (aDict->isDict()) {
MA.parseMovieActivation(aDict);
}
} else {
ok = false;
}
}
Movie::Movie(const Movie &other)
{
ok = other.ok;
rotationAngle = other.rotationAngle;
width = other.width;
height = other.height;
showPoster = other.showPoster;
MA = other.MA;
poster = other.poster.copy();
if (other.fileName) {
fileName = other.fileName->copy();
} else {
fileName = nullptr;
}
}
void Movie::getFloatingWindowSize(int *widthA, int *heightA)
{
*widthA = int(width * double(MA.znum) / MA.zdenum);
*heightA = int(height * double(MA.znum) / MA.zdenum);
}
std::unique_ptr<Movie> Movie::copy() const
{
return std::make_unique<Movie>(*this);
}