diff --git a/sound/imp/audiere_imp.cpp b/sound/imp/audiere_imp.cpp index 266fcb2e25..ecdb0580ad 100644 --- a/sound/imp/audiere_imp.cpp +++ b/sound/imp/audiere_imp.cpp @@ -27,6 +27,7 @@ AudiereManager::AudiereManager() canRepeatStream = true; canLoadFile = true; canLoadSource = false; + canLoadStream = false; device = OpenDevice(""); diff --git a/sound/imp/audiere_imp.h b/sound/imp/audiere_imp.h index 083e33258c..480611ce3d 100644 --- a/sound/imp/audiere_imp.h +++ b/sound/imp/audiere_imp.h @@ -19,6 +19,10 @@ class AudiereManager : public Manager virtual Sound *load(const std::string &file, bool stream=false); + /// not implemented yet + virtual Sound *load(Stream::InputStream *input, bool stream=false) + { assert(0); } + /// disabled virtual Sound *load(InputSource *input, bool stream=false) { assert(0); } diff --git a/sound/imp/input_ffmpeg.cpp b/sound/imp/input_ffmpeg.cpp index 9ce822444b..f29ddfdb64 100644 --- a/sound/imp/input_ffmpeg.cpp +++ b/sound/imp/input_ffmpeg.cpp @@ -32,6 +32,8 @@ FFM_InputManager::FFM_InputManager() av_log_set_level(AV_LOG_ERROR); init = true; } + + canLoadStream = false; } InputSource *FFM_InputManager::load(const std::string &file) diff --git a/sound/imp/input_ffmpeg.h b/sound/imp/input_ffmpeg.h index 8c19d381e1..cc8feffd40 100644 --- a/sound/imp/input_ffmpeg.h +++ b/sound/imp/input_ffmpeg.h @@ -34,6 +34,9 @@ class FFM_InputManager : public InputManager public: FFM_InputManager(); virtual InputSource *load(const std::string &file); + + /// not supported + virtual InputSource *load(Stream::InputStream *input) { assert(0); } }; /// FFMpeg implementation of InputSource diff --git a/sound/imp/input_filter.h b/sound/imp/input_filter.h index f81f1e8a5e..c3da8599d2 100644 --- a/sound/imp/input_filter.h +++ b/sound/imp/input_filter.h @@ -43,26 +43,31 @@ class InputFilter : public Manager /// Assign an input manager and a sound manager to this object void set(Manager *_snd, InputManager *_inp) - { - inp = _inp; - snd = _snd; - - needsUpdate = snd->needsUpdate; - has3D = snd->has3D; - canRepeatStream = snd->canRepeatStream; - - // Both these should be true, or the use of this class is pretty - // pointless - canLoadSource = snd->canLoadSource; - canLoadFile = canLoadSource; - assert(canLoadSource && canLoadFile); - } + { + inp = _inp; + snd = _snd; + + // Set capabilities + needsUpdate = snd->needsUpdate; + has3D = snd->has3D; + canRepeatStream = snd->canRepeatStream; + canLoadStream = inp->canLoadStream; + + // Both these should be true, or the use of this class is pretty + // pointless + canLoadSource = snd->canLoadSource; + canLoadFile = canLoadSource; + assert(canLoadSource && canLoadFile); + } virtual Sound *load(const std::string &file, bool stream=false) - { return load(inp->load(file), stream); } + { return load(inp->load(file), stream); } + + virtual Sound *load(Stream::InputStream *input, bool stream=false) + { return load(inp->load(input), stream); } virtual Sound *load(InputSource *input, bool stream=false) - { return snd->load(input, stream); } + { return snd->load(input, stream); } virtual void update() { snd->update(); } virtual void setListenerPos(float x, float y, float z, diff --git a/sound/imp/output_openal.cpp b/sound/imp/output_openal.cpp index c56e8c3798..190d0638d3 100644 --- a/sound/imp/output_openal.cpp +++ b/sound/imp/output_openal.cpp @@ -97,6 +97,9 @@ OpenAL_Manager::~OpenAL_Manager() Sound *OpenAL_Manager::load(const std::string &file, bool stream) { assert(0 && "OpenAL cannot decode files"); } +Sound *OpenAL_Manager::load(Stream::InputStream*,bool) +{ assert(0 && "OpenAL cannot decode streams"); } + Sound *OpenAL_Manager::load(InputSource *source, bool stream) { return new OpenAL_Sound(source, this, stream); } diff --git a/sound/imp/output_openal.h b/sound/imp/output_openal.h index 41f801e5a6..bf92197df2 100644 --- a/sound/imp/output_openal.h +++ b/sound/imp/output_openal.h @@ -26,6 +26,7 @@ public: void remove_stream(LST::iterator); virtual Sound *load(const std::string &file, bool stream=false); + virtual Sound *load(Stream::InputStream *input, bool stream=false); virtual Sound *load(InputSource* input, bool stream=false); virtual void update(); virtual void setListenerPos(float x, float y, float z, diff --git a/sound/input.h b/sound/input.h index b030885fb4..d27de97a63 100644 --- a/sound/input.h +++ b/sound/input.h @@ -4,6 +4,8 @@ #include #include +#include "../stream/input.h" + namespace Mangle { namespace Sound { @@ -64,9 +66,15 @@ class InputSource class InputManager { public: + /// If true, the stream version of load() works + bool canLoadStream; + /// Load a sound input source from file virtual InputSource *load(const std::string &file) = 0; + /// Load a sound input source from stream (if canLoadStream is true) + virtual InputSource *load(Stream::InputStream *input) = 0; + /// Virtual destructor virtual ~InputManager() {} }; diff --git a/sound/sound.h b/sound/sound.h index 0d1aecf6e9..90407141ed 100644 --- a/sound/sound.h +++ b/sound/sound.h @@ -4,6 +4,8 @@ #include #include "input.h" +#include "../stream/input.h" + namespace Mangle { namespace Sound { @@ -115,6 +117,9 @@ class Manager /// true if we can load sounds from an InputSource bool canLoadSource; + /// If true, we can lound sound files from a Stream + bool canLoadStream; + /** @brief Load a sound from an input source. Only valid if canLoadSource is true. @@ -132,6 +137,16 @@ class Manager */ virtual Sound *load(InputSource *input, bool stream=false) = 0; + /** + @brief Load a sound directly from file. Only valid if canLoadStream + is true. + + @param input audio file stream + @param stream true if the file should be streamed + @see load(InputSource*,bool) + */ + virtual Sound *load(Stream::InputStream *input, bool stream=false) = 0; + /** @brief Load a sound directly from file. Only valid if canLoadFile is true. diff --git a/stream/imp_client/audiere_file.cpp b/stream/imp_client/audiere_file.cpp new file mode 100644 index 0000000000..ea8142eb49 --- /dev/null +++ b/stream/imp_client/audiere_file.cpp @@ -0,0 +1,39 @@ +#include "audiere_file.h" + +using namespace audiere; +using namespace Mangle::Stream; + +bool AudiereFile::seek(int pos, SeekMode mode) +{ + assert(inp->isSeekable); + assert(inp->hasPosition); + + if(mode == BEGIN) + { + // Absolute position + inp->seek(pos); + return inp->tell() == pos; + } + if(mode == CURRENT) + { + // Current position + int cpos = inp->tell(); + + // Seek to a elative position + inp->seek(cpos + pos); + return inp->tell() == (pos+cpos); + } + if(mode == END) + { + // Seeking from the end. This requires that we're able to get + // the entire size of the file. The pos also has to be + // non-positive. + assert(inp->hasSize); + assert(pos <= 0); + + size_t epos = inp->size(); + inp->seek(epos + pos); + return inp->tell() == (epos+pos); + } + assert(0 && "invalid seek mode"); +} diff --git a/stream/imp_client/audiere_file.h b/stream/imp_client/audiere_file.h new file mode 100644 index 0000000000..201a7629ac --- /dev/null +++ b/stream/imp_client/audiere_file.h @@ -0,0 +1,35 @@ +#ifndef MANGLE_STREAM_AUDIERECLIENT_H +#define MANGLE_STREAM_AUDIERECLIENT_H + +#include +#include +#include "iwrapper.h" + +namespace Mangle { +namespace Stream { + +/** @brief An Audiere::File that wraps a Mangle::Stream input. + + This lets Audiere read sound files from any generic archive or + file manager that supports Mangle streams. + */ +class AudiereFile : public audiere::File, _IWrapper +{ + public: + AudiereFile(InputStream *inp, bool autoDel=false) + : _IWrapper(inp, autoDel) {} + + /// Read 'count' bytes, return bytes successfully read + int read(void *buf, int count) + { return inp->read(buf,count); } + + /// Seek, relative to specified seek mode. Returns true if successful. + bool seek(int pos, audiere::SeekMode mode); + + /// Get current position + int tell() + { assert(inp->hasPosition); return inp->tell(); } +}; + +}} // namespaces +#endif diff --git a/stream/imp_server/ogre_datastream.h b/stream/imp_server/ogre_datastream.h new file mode 100644 index 0000000000..ef922fa7f8 --- /dev/null +++ b/stream/imp_server/ogre_datastream.h @@ -0,0 +1,35 @@ +#ifndef MANGLE_STREAM_OGRESERVER_H +#define MANGLE_STREAM_OGRESERVER_H + +#include + +namespace Mangle { +namespace Stream { + +/** A Stream wrapping an OGRE DataStream. + + This has been built and tested against OGRE 1.6.2. You might have + to make your own modifications if you're working with newer (or + older) versions. + */ +class OgreStream : public InputStream +{ + Ogre::DataStreamPtr inp; + + public: + OgreStream(Ogre::DataStreamPtr _inp) : inp(_inp) + { + isSeekable = true; + hasPosition = true; + hasSize = true; + } + + size_t read(void *buf, size_t count) { return inp->read(buf,count); } + void seek(size_t pos) { inp->seek(pos); } + size_t tell() const { return inp->tell(); } + size_t size() const { return inp->size(); } + bool eof() const { return inp->eof(); } +}; + +}} // namespaces +#endif diff --git a/vfs/imp_client/ogre_archive.h b/vfs/imp_client/ogre_archive.h index f72398a2de..70e6045c4e 100644 --- a/vfs/imp_client/ogre_archive.h +++ b/vfs/imp_client/ogre_archive.h @@ -18,7 +18,6 @@ namespace VFS { class MangleArchive : public Ogre::Archive, _Wrapper { public: - /// Constructor without name MangleArchive(VFS *vfs, const std::string &name, const std::string &archType = "Mangle", bool autoDel=false) diff --git a/vfs/imp_server/ogre_vfs.h b/vfs/imp_server/ogre_vfs.h new file mode 100644 index 0000000000..98cf5da79b --- /dev/null +++ b/vfs/imp_server/ogre_vfs.h @@ -0,0 +1,62 @@ +#ifndef MANGLE_VFS_OGRECLIENT_H +#define MANGLE_VFS_OGRECLIENT_H + +#include + +namespace Mangle { +namespace VFS { + +/** @brief An interface into the OGRE VFS system. + + This class does not wrap a single Ogre::Archive, but rather the + entire resource set available to Ogre. You can use this class to + tap into all paths, Zip files, custom archives on so on that have + been inserted into Ogre as resource locations. + + This class is currently a work in progres, it will not compile as + it stands. + + This has been built and tested against OGRE 1.6.2. You might have + to make your own modifications if you're working with newer (or + older) versions. + */ +class OgreVFS : public VFS +{ + public: + OgreVFS() + { + hasFind = true; + isCaseSensitive = true; + } + + /// Open a new data stream. Deleting the object should be enough to + /// close it. + virtual Stream::InputStream *open(const std::string &name); + + /// Check for the existence of a file + virtual bool isFile(const std::string &name) const; + + /// Check for the existence of a directory + virtual bool isDir(const std::string &name) const; + + /// Get info about a single file + virtual FileInfo stat(const std::string &name) const; + + /// List all entries in a given directory. A blank dir should be + /// interpreted as a the root/current directory of the archive. If + /// dirs is true, list directories instead of files. + virtual FileInfoList list(const std::string& dir = "", + bool recurse=true, + bool dirs=false) const; + + /// Find files after a given pattern. Wildcards (*) are + /// supported. Only valid if 'hasFind' is true. Don't implement your + /// own pattern matching here if the backend doesn't support it + /// natively; use a filter instead (not implemented yet.) + virtual FileInfoList find(const std::string& pattern, + bool recursive=true, + bool dirs=false) const; +}; + +}} // namespaces +#endif