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 Graphics.cpp
mapHandler.cpp mapHandler.cpp
NetPacksClient.cpp NetPacksClient.cpp
SDLRWwrapper.cpp
) )
set(client_HEADERS set(client_HEADERS

View File

@ -3,6 +3,7 @@
#include "CMusicHandler.h" #include "CMusicHandler.h"
#include "CGameInfo.h" #include "CGameInfo.h"
#include "SDLRWwrapper.h"
#include "../lib/CCreatureHandler.h" #include "../lib/CCreatureHandler.h"
#include "../lib/spells/CSpellHandler.h" #include "../lib/spells/CSpellHandler.h"
#include "../lib/JsonNode.h" #include "../lib/JsonNode.h"
@ -303,7 +304,7 @@ void CMusicHandler::release()
void CMusicHandler::playMusic(std::string musicURI, bool loop) void CMusicHandler::playMusic(std::string musicURI, bool loop)
{ {
if (current && current->isTrack( musicURI)) if (current && current->isTrack(musicURI))
return; return;
queueNext(this, "", musicURI, loop); queueNext(this, "", musicURI, loop);
@ -342,7 +343,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
return; return;
} }
if (current && current->isTrack( selectedEntry->second)) if (current && current->isTrack(selectedEntry->second))
return; return;
// in this mode - play specific track from set // 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): MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
owner(owner), owner(owner),
music(nullptr), music(nullptr),
musicFile(nullptr),
loop(looped ? -1 : 1), loop(looped ? -1 : 1),
setName(setName) setName(std::move(setName))
{ {
if (!musicURI.empty()) if (!musicURI.empty())
load(musicURI); load(std::move(musicURI));
} }
MusicEntry::~MusicEntry() MusicEntry::~MusicEntry()
{ {
@ -448,15 +448,12 @@ void MusicEntry::load(std::string musicURI)
logGlobal->traceStream()<<"Loading music file "<<musicURI; logGlobal->traceStream()<<"Loading music file "<<musicURI;
data = CResourceHandler::get()->load(ResourceID(musicURI, EResType::MUSIC))->readAll(); auto musicFile = MakeSDLRWops(CResourceHandler::get()->load(ResourceID(std::move(musicURI), EResType::MUSIC)));
musicFile = SDL_RWFromConstMem(data.first.get(), data.second);
music = Mix_LoadMUS_RW(musicFile, SDL_FALSE); music = Mix_LoadMUS_RW(musicFile, SDL_TRUE);
if(!music) if(!music)
{ {
SDL_FreeRW(musicFile);
musicFile = nullptr;
logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError(); logGlobal->warnStream() << "Warning: Cannot open " << currentName << ": " << Mix_GetError();
return; return;
} }

View File

@ -80,10 +80,8 @@ class CMusicHandler;
//Class for handling one music file //Class for handling one music file
class MusicEntry class MusicEntry
{ {
std::pair<std::unique_ptr<ui8[]>, size_t> data;
CMusicHandler *owner; CMusicHandler *owner;
Mix_Music *music; Mix_Music *music;
SDL_RWops *musicFile;
int loop; // -1 = indefinite int loop; // -1 = indefinite
//if not null - set from which music will be randomly selected //if not null - set from which music will be randomly selected

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="Graphics.h" />
<Unit filename="NetPacksClient.cpp" /> <Unit filename="NetPacksClient.cpp" />
<Unit filename="SDLMain.h" /> <Unit filename="SDLMain.h" />
<Unit filename="SDLRWwrapper.cpp" />
<Unit filename="SDLRWwrapper.h" />
<Unit filename="StdInc.h"> <Unit filename="StdInc.h">
<Option weight="0" /> <Option weight="0" />
</Unit> </Unit>