1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

support for music streaming

This commit is contained in:
Zyx-2000 2016-01-30 22:34:46 +01:00
parent 4e8486da7b
commit 33d0738859
6 changed files with 104 additions and 15 deletions

View File

@ -57,6 +57,7 @@ set(client_SRCS
Graphics.cpp
mapHandler.cpp
NetPacksClient.cpp
SDLRWwrapper.cpp
)
set(client_HEADERS

View File

@ -3,6 +3,7 @@
#include "CMusicHandler.h"
#include "CGameInfo.h"
#include "SDLRWwrapper.h"
#include "../lib/CCreatureHandler.h"
#include "../lib/spells/CSpellHandler.h"
#include "../lib/JsonNode.h"
@ -86,7 +87,7 @@ CSoundHandler::CSoundHandler():
listener(std::bind(&CSoundHandler::onVolumeChange, this, _1));
// Vectors for helper(s)
pickupSounds =
pickupSounds =
{
soundBase::pickup01, soundBase::pickup02, soundBase::pickup03,
soundBase::pickup04, soundBase::pickup05, soundBase::pickup06, soundBase::pickup07
@ -303,7 +304,7 @@ void CMusicHandler::release()
void CMusicHandler::playMusic(std::string musicURI, bool loop)
{
if (current && current->isTrack( musicURI))
if (current && current->isTrack(musicURI))
return;
queueNext(this, "", musicURI, loop);
@ -342,7 +343,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
return;
}
if (current && current->isTrack( selectedEntry->second))
if (current && current->isTrack(selectedEntry->second))
return;
// in this mode - play specific track from set
@ -421,12 +422,11 @@ void CMusicHandler::musicFinishedCallback(void)
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
owner(owner),
music(nullptr),
musicFile(nullptr),
loop(looped ? -1 : 1),
setName(setName)
setName(std::move(setName))
{
if (!musicURI.empty())
load(musicURI);
load(std::move(musicURI));
}
MusicEntry::~MusicEntry()
{
@ -448,15 +448,12 @@ void MusicEntry::load(std::string musicURI)
logGlobal->traceStream()<<"Loading music file "<<musicURI;
data = CResourceHandler::get()->load(ResourceID(musicURI, EResType::MUSIC))->readAll();
musicFile = SDL_RWFromConstMem(data.first.get(), data.second);
music = Mix_LoadMUS_RW(musicFile, SDL_FALSE);
auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourceID(std::move(musicURI), EResType::MUSIC)));
music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
if(!music)
{
SDL_FreeRW(musicFile);
musicFile = nullptr;
logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
return;
}

View File

@ -80,10 +80,8 @@ class CMusicHandler;
//Class for handling one music file
class MusicEntry
{
std::pair<std::unique_ptr<ui8[]>, size_t> data;
CMusicHandler *owner;
Mix_Music *music;
SDL_RWops *musicFile;
int loop; // -1 = indefinite
//if not null - set from which music will be randomly selected
@ -116,7 +114,7 @@ private:
std::unique_ptr<MusicEntry> current;
std::unique_ptr<MusicEntry> next;
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
void queueNext(std::unique_ptr<MusicEntry> queued);

85
client/SDLRWwrapper.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "StdInc.h"
#include "SDLRWwrapper.h"
#include "../lib/filesystem/CInputStream.h"
#include <SDL_rwops.h>
static inline CInputStream* get_stream(SDL_RWops* context)
{
return static_cast<CInputStream*>(context->hidden.unknown.data1);
}
static Sint64 impl_size(SDL_RWops* context)
{
return get_stream(context)->getSize();
}
static Sint64 impl_seek(SDL_RWops* context, Sint64 offset, int whence)
{
auto stream = get_stream(context);
switch (whence)
{
case RW_SEEK_SET:
return stream->seek(offset);
break;
case RW_SEEK_CUR:
return stream->seek(stream->tell() + offset);
break;
case RW_SEEK_END:
return stream->seek(stream->getSize() + offset);
break;
default:
return -1;
}
}
static std::size_t impl_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum)
{
auto stream = get_stream(context);
auto oldpos = stream->tell();
auto count = stream->read(static_cast<ui8*>(ptr), size*maxnum);
if (count != 0 && count != size*maxnum)
{
// if not a whole amount of objects of size has been read, we need to seek
stream->seek(oldpos + size * (count / size));
}
return count / size;
}
static std::size_t impl_write(SDL_RWops* context, const void *ptr, size_t size, size_t num)
{
// writing is not supported
return 0;
}
static int impl_close(SDL_RWops* context)
{
if (context == nullptr)
return 0;
delete get_stream(context);
SDL_FreeRW(context);
return 0;
}
SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in)
{
SDL_RWops* result = SDL_AllocRW();
if (!result)
return nullptr;
result->size = &impl_size;
result->seek = &impl_seek;
result->read = &impl_read;
result->write = &impl_write;
result->close = &impl_close;
result->type = SDL_RWOPS_UNKNOWN;
result->hidden.unknown.data1 = in.release();
return result;
}

6
client/SDLRWwrapper.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
struct SDL_RWops;
class CInputStream;
SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in);

View File

@ -126,6 +126,8 @@
<Unit filename="Graphics.h" />
<Unit filename="NetPacksClient.cpp" />
<Unit filename="SDLMain.h" />
<Unit filename="SDLRWwrapper.cpp" />
<Unit filename="SDLRWwrapper.h" />
<Unit filename="StdInc.h">
<Option weight="0" />
</Unit>