mirror of
https://github.com/blupi-games/planetblupi
synced 2024-12-30 10:15:36 +01:00
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.
349 lines
7.6 KiB
C++
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;
|
|
}
|