| //********************************************************************************* |
| // 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); |
| } |