1
0
mirror of https://github.com/blupi-games/planetblupi synced 2024-12-30 10:15:36 +01:00
planetblupi/src/movie.cxx
Mathieu Schroeter 8b7142a084 Add the option for chaning the render quality
It toggles between 'nearest' (faster) and 'best' (slower but more
prettier). It's enabled only when the game runs in fullscreen.

The option can be passed by command line argument `--render-quality on`,
by settings.json file with a `"renderquality": true` entry or simply
with the main settings screen in the game.
2018-08-06 07:20:23 +02:00

349 lines
7.6 KiB
C++

/*
* This file is part of the planetblupi source code
* Copyright (C) 1997, Daniel Roux & EPSITEC SA
* Copyright (C) 2017-2018, Mathieu Schroeter
* http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games
*
* 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 3 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, see http://gnu.org/licenses
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL_image.h>
#include "kitchensink/kitchensink.h"
#include "blupi.h"
#include "def.h"
#include "display.h"
#include "event.h"
#include "misc.h"
#include "movie.h"
// Initialize avi libraries.
bool
CMovie::initAVI ()
{
// Initialize Kitchensink with network support and all formats.
Sint32 err = Kit_Init (0);
if (err != 0)
{
fprintf (stderr, "Unable to initialize Kitchensink: %s", Kit_GetError ());
return false;
}
return true;
}
// Closes the opened AVI file and the opened device type. |
void
CMovie::termAVI ()
{
Kit_Quit ();
}
// Close the movie and anything associated with it. |
// This function clears the <m_fPlaying> and <m_fMovieOpen> flags |
void
CMovie::fileCloseMovie ()
{
m_fPlaying = false; // can't be playing any longer
m_fMovieOpen = false; // no more movies open
if (m_videoTex)
{
SDL_DestroyTexture (m_videoTex);
m_videoTex = nullptr;
}
if (this->backTexture)
{
SDL_DestroyTexture (this->backTexture);
this->backTexture = nullptr;
}
if (m_player)
{
SDL_CloseAudioDevice (m_audioDev);
Kit_ClosePlayer (m_player);
m_player = nullptr;
}
if (m_movie)
{
Kit_CloseSource (m_movie);
SDL_RWclose (this->rw_ops);
m_movie = nullptr;
}
}
// Open an AVI movie. Use CommDlg open box to
// open and then handle the initialization to
// show the movie and position it properly. Keep
// the movie paused when opened.
// Sets <m_fMovieOpen> on success.
bool
CMovie::fileOpenMovie (const std::string & pFilename)
{
const auto path = GetBaseDir () + pFilename;
// we got a filename, now close any old movie and open the new one. */
if (m_fMovieOpen)
fileCloseMovie ();
this->rw_ops = SDL_RWFromFile (path.c_str (), "rb");
if (!this->rw_ops)
return false;
// Open up the sourcefile.
// This can be a local file, network url, ...
m_movie = Kit_CreateSourceFromRW (rw_ops);
if (m_movie)
{
// Create the player
m_player = Kit_CreatePlayer (
m_movie, Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_VIDEO),
Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_AUDIO),
Kit_GetBestSourceStream (m_movie, KIT_STREAMTYPE_SUBTITLE), LXIMAGE (),
LYIMAGE ());
if (m_player == nullptr)
return false;
Kit_PlayerInfo info;
Kit_GetPlayerInfo (m_player, &info);
SDL_AudioSpec wanted_spec, audio_spec;
SDL_memset (&wanted_spec, 0, sizeof (wanted_spec));
wanted_spec.freq = info.audio.output.samplerate;
wanted_spec.format = info.audio.output.format;
wanted_spec.channels = info.audio.output.channels;
m_audioDev = SDL_OpenAudioDevice (nullptr, 0, &wanted_spec, &audio_spec, 0);
SDL_PauseAudioDevice (m_audioDev, 0);
if (g_bFullScreen && g_zoom == 1)
SDL_SetHint (
SDL_HINT_RENDER_SCALE_QUALITY, g_renderQuality ? "best" : "nearest");
m_videoTex = SDL_CreateTexture (
g_renderer, info.video.output.format, SDL_TEXTUREACCESS_TARGET,
info.video.output.width, info.video.output.height);
if (g_bFullScreen && g_zoom == 1)
SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearset");
if (m_videoTex == nullptr)
return false;
std::string backWideName = "";
if (Display::getDisplay ().isWide ())
{
if (path.rfind ("win005.mkv") != std::string::npos)
backWideName = "image/back-disco.png";
else if (path.rfind ("win129.mkv") != std::string::npos)
backWideName = "image/back-stars.png";
}
std::string file = GetBaseDir () + backWideName;
SDL_Surface * surface = IMG_Load (file.c_str ());
this->backTexture = SDL_CreateTextureFromSurface (g_renderer, surface);
SDL_FreeSurface (surface);
return true;
}
else
{
// generic error for open
m_fMovieOpen = false;
return false;
}
}
// Play/pause the movie depending on the state
void
CMovie::playMovie ()
{
m_fPlaying = !m_fPlaying; // swap the play flag
// play/pause the AVI movie
if (m_fPlaying)
{
this->starting = true;
Kit_PlayerPlay (m_player);
}
else
Kit_PlayerPause (m_player);
}
CMovie::CMovie (CPixmap * pixmap)
{
this->pixmap = pixmap;
m_bEnable = false;
m_fPlaying = false;
m_fMovieOpen = false;
m_movie = nullptr;
m_player = nullptr;
m_videoTex = nullptr;
memset (m_audiobuf, 0, sizeof (m_audiobuf));
this->rw_ops = nullptr;
m_ret = 0;
}
CMovie::~CMovie ()
{
termAVI ();
}
// Ouvre la librairie avi.
bool
CMovie::Create ()
{
m_bEnable = initAVI ();
return m_bEnable;
}
// Retourne l'état de DirectMovie.
bool
CMovie::GetEnable ()
{
return m_bEnable;
}
// Montre un film avi.
bool
CMovie::Play (const std::string & pFilename)
{
if (!m_bEnable)
return false;
if (!fileOpenMovie (pFilename))
return false;
playMovie ();
CEvent::PushUserEvent (EV_MOVIE_PLAY);
return true;
}
// Stoppe le film avi.
void
CMovie::Stop ()
{
if (!m_bEnable)
return;
fileCloseMovie ();
}
void
CMovie::Pause ()
{
if (!m_bEnable || !m_fPlaying)
return;
if (Kit_GetPlayerState (m_player) != KIT_PLAYING)
return;
Kit_PlayerPause (m_player);
}
void
CMovie::Resume ()
{
if (!m_bEnable || !m_fPlaying)
return;
if (Kit_GetPlayerState (m_player) != KIT_PAUSED)
return;
Kit_PlayerPlay (m_player);
}
bool
CMovie::Render ()
{
if (!m_bEnable || !m_fPlaying)
return false;
if (Kit_GetPlayerState (m_player) == KIT_STOPPED)
return false;
// Refresh audio
if (SDL_GetQueuedAudioSize (m_audioDev) < AUDIOBUFFER_SIZE)
{
Sint32 need = AUDIOBUFFER_SIZE - m_ret;
SDL_LockAudio ();
while (need > 0)
{
m_ret = Kit_GetPlayerAudioData (
m_player, (unsigned char *) m_audiobuf,
AUDIOBUFFER_SIZE - (size_t) SDL_GetQueuedAudioSize (m_audioDev));
need -= m_ret;
if (m_ret > 0)
SDL_QueueAudio (m_audioDev, m_audiobuf, m_ret);
else
break;
}
SDL_UnlockAudio ();
SDL_PauseAudioDevice (m_audioDev, 0);
}
if (this->starting)
{
SDL_SetRenderTarget (g_renderer, m_videoTex);
SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 255);
SDL_RenderClear (g_renderer);
SDL_SetRenderTarget (g_renderer, nullptr);
this->starting = false;
}
if (!this->backTexture)
{
// Clear screen with black
SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 255);
SDL_RenderClear (g_renderer);
}
else
SDL_RenderCopy (g_renderer, this->backTexture, nullptr, nullptr);
// Refresh videotexture and render it
Kit_GetPlayerVideoData (m_player, m_videoTex);
SDL_Rect dstRect;
dstRect.x = (LXIMAGE () - LXLOGIC ()) / 2;
dstRect.y = 0;
dstRect.w = LXLOGIC ();
dstRect.h = LYLOGIC ();
SDL_RenderCopy (g_renderer, m_videoTex, nullptr, &dstRect);
SDL_RenderPresent (g_renderer);
CEvent::PushUserEvent (EV_MOVIE_PLAY);
return true;
}