diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e34ebf779..fcd372d3c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" S set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}") -option( NO_FMOD "Disable FMODEx sound support" ) -option( NO_OPENAL "Disable OpenAL sound support" ) +option( NO_FMOD "Disable FMODEx sound support" OFF ) +option( NO_OPENAL "Disable OpenAL sound support" OFF ) find_package( BZip2 ) find_package( JPEG ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c77b9e3b4..822f103312 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,64 +121,6 @@ if( WIN32 ) message( FATAL_ERROR "Could not find DirectX 9 libraries" ) endif( NOT DX_LIBS_FOUND ) - - if( NOT NO_OPENAL ) - SET( GST_SEARCH_PATHS - ENV GSTSDK_DIR - ENV MINGDIR - "C:/Program Files/gstreamer" - "C:/gstreamer" ) - - message( STATUS "Looking for glib.h" ) - find_path( GLIB_INCLUDE_DIR glib.h - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES include include/glib-2.0 ) - if( GLIB_INCLUDE_DIR ) - message(STATUS "Looking for glib.h - found: ${GLIB_INCLUDE_DIR}") - else( GLIB_INCLUDE_DIR ) - message(STATUS "Looking for glib.h - not found") - endif( GLIB_INCLUDE_DIR ) - - message( STATUS "Looking for gst/gst.h" ) - find_path( GST_INCLUDE_DIR gst/gst.h - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES include include/gstreamer-0.10 ) - if( GST_INCLUDE_DIR ) - message( STATUS "Looking for gst/gst.h - found: ${GST_INCLUDE_DIR}" ) - else( GST_INCLUDE_DIR ) - message( STATUS "Looking for gst/gst.h - not found" ) - endif( GST_INCLUDE_DIR ) - - message( STATUS "Looking for al.h" ) - set( OPENAL_SEARCH_PATHS - ENV ALSDK_DIR - ENV MINGDIR - "C:/Program Files/OpenAL 1.1 SDK" - "C:/Program Files (x86)/OpenAL 1.1 SDK" - "E:/Programs/Dev/OpenAL" - "E:/Program Files (x86)/OpenAL 1.1 SDK" ) - - find_path( OPENAL_INCLUDE_DIR al.h - PATHS ${OPENAL_SEARCH_PATHS} - PATH_SUFFIXES include include/AL ) - if( OPENAL_INCLUDE_DIR ) - message( STATUS "Looking for al.h - found: ${OPENAL_INCLUDE_DIR}" ) - else( OPENAL_INCLUDE_DIR ) - message( STATUS "Looking for al.h - not found" ) - endif( OPENAL_INCLUDE_DIR ) - - if( NOT OPENAL_INCLUDE_DIR ) - set( NO_OPENAL ON ) - else( NOT OPENAL_INCLUDE_DIR ) - include_directories( ${OPENAL_INCLUDE_DIR} ) - if( GLIB_INCLUDE_DIR AND GST_INCLUDE_DIR ) - include_directories( ${OPENAL_INCLUDE_DIR} ${GLIB_INCLUDE_DIR} ${GST_INCLUDE_DIR} ) - set( WITH_GSTREAMER ON ) - endif( GLIB_INCLUDE_DIR AND GST_INCLUDE_DIR ) - endif( NOT OPENAL_INCLUDE_DIR ) - endif( NOT NO_OPENAL ) - - set( ZDOOM_LIBS wsock32 winmm @@ -193,71 +135,12 @@ if( WIN32 ) ws2_32 setupapi oleaut32 ) - - if( NOT NO_OPENAL ) - message( STATUS "Looking for OpenAL library" ) - find_library( OPENAL_LIBRARY NAMES OpenAL32 - PATHS ${OPENAL_SEARCH_PATHS} - PATH_SUFFIXES lib ) - - if( NOT OPENAL_LIBRARY ) - set( NO_OPENAL ON ) - message( STATUS "Looking for OpenAL library - not found" ) - else( NOT OPENAL_LIBRARY ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${OPENAL_LIBRARY}" ) - message( STATUS "Looking for OpenAL library - found" ) - endif( NOT OPENAL_LIBRARY ) - - if( WITH_GSTREAMER AND NOT NO_OPENAL ) - message( STATUS "Looking for GST libraries" ) - find_library( GST_LIBRARY1 NAMES gstapp-0.10 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY2 NAMES gstaudio-0.10 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY3 NAMES gstreamer-0.10 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY4 NAMES gthread-2.0 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY5 NAMES gmodule-2.0 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY6 NAMES gobject-2.0 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - find_library( GST_LIBRARY7 NAMES glib-2.0 - PATHS ${GST_SEARCH_PATHS} - PATH_SUFFIXES lib ) - - if( GST_LIBRARY1 AND GST_LIBRARY2 AND GST_LIBRARY3 AND GST_LIBRARY4 AND GST_LIBRARY5 AND GST_LIBRARY6 AND GST_LIBRARY7 ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "${GST_LIBRARY1}" "${GST_LIBRARY2}" "${GST_LIBRARY3}" "${GST_LIBRARY4}" "${GST_LIBRARY5}" "${GST_LIBRARY6}" "${GST_LIBRARY7}" ) - message( STATUS "Looking for GST libraries - found" ) - else( GST_LIBRARY1 AND GST_LIBRARY2 AND GST_LIBRARY3 AND GST_LIBRARY4 AND GST_LIBRARY5 AND GST_LIBRARY6 AND GST_LIBRARY7 ) - set( WITH_GSTREAMER OFF ) - message( STATUS "Looking for GST libraries - not found" ) - endif( GST_LIBRARY1 AND GST_LIBRARY2 AND GST_LIBRARY3 AND GST_LIBRARY4 AND GST_LIBRARY5 AND GST_LIBRARY6 AND GST_LIBRARY7 ) - endif( WITH_GSTREAMER AND NOT NO_OPENAL ) - endif( NOT NO_OPENAL ) else( WIN32 ) if( APPLE ) set( FMOD_SEARCH_PATHS "/Developer/FMOD Programmers API Mac/api" ) set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES inc ) set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib ) set( NO_GTK ON ) - - if( NOT NO_OPENAL ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} "-framework OpenAL") - - check_library_exists( gstapp-0.10 gst_app_src_set_callbacks "" HAS_GSTAPP ) - check_library_exists( gstaudio-0.10 gst_audio_set_channel_positions "" HAS_GSTAUDIO ) - if( HAS_GSTAPP AND HAS_GSTAUDIO ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} gstapp-0.10 gst-audio-0.10 "-framework OpenAL") - set( WITH_GSTREAMER ON ) - endif( HAS_GSTAPP AND HAS_GSTAUDIO ) - endif( NOT NO_OPENAL ) else( APPLE ) option( NO_GTK "Disable GTK+ dialogs (Not applicable to Windows)" ) option( VALGRIND "Add special Valgrind sequences to self-modifying code" ) @@ -284,21 +167,6 @@ else( WIN32 ) endif( GTK2_FOUND ) endif( NOT NO_GTK ) - pkg_check_modules( OPENAL openal ) - if( NOT OPENAL_FOUND ) - set( NO_OPENAL ON ) - else( NOT OPENAL_FOUND ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${OPENAL_LIBRARIES} ) - include_directories( ${OPENAL_INCLUDE_DIRS} ) - - pkg_check_modules( GSTREAMER gstreamer-app-0.10>=0.10.23 gstreamer-audio-0.10 ) - if( GSTREAMER_FOUND ) - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GSTREAMER_LIBRARIES} ) - include_directories( ${GSTREAMER_INCLUDE_DIRS} ) - set( WITH_GSTREAMER ON ) - endif( GSTREAMER_FOUND ) - endif( NOT OPENAL_FOUND ) - # Check for Xcursor library and header files find_library( XCURSOR_LIB Xcursor ) if( XCURSOR_LIB ) @@ -334,6 +202,16 @@ else( WIN32 ) endif( WIN32 ) +if( NOT NO_OPENAL ) + find_package( OpenAL ) + if( OPENAL_FOUND ) + include_directories( ${OPENAL_INCLUDE_DIR} ) + set( ZDOOM_LIBS ${OPENAL_LIBRARY} ${ZDOOM_LIBS} ) + else( OPENAL_FOUND ) + set( NO_OPENAL ON ) + endif( OPENAL_FOUND ) +endif( NOT NO_OPENAL ) + if( NOT NO_FMOD ) # Search for FMOD include files if( NOT WIN32 ) @@ -395,8 +273,6 @@ if( NO_FMOD ) endif( NO_FMOD ) if( NO_OPENAL ) add_definitions( -DNO_OPENAL=1 ) -elseif( WITH_GSTREAMER ) - add_definitions( -DWITH_GSTREAMER=1 ) endif( NO_OPENAL ) # Search for FluidSynth diff --git a/src/sound/oalsound.cpp b/src/sound/oalsound.cpp index bddbcdb483..5bbd245227 100644 --- a/src/sound/oalsound.cpp +++ b/src/sound/oalsound.cpp @@ -210,1268 +210,6 @@ static ALenum FormatFromDesc(int bits, int channels) } -#ifdef WITH_GSTREAMER -#include -#include -#include -#include -#include - -/* Bad GStreamer, using enums for bit fields... */ -static GstMessageType operator|(const GstMessageType &a, const GstMessageType &b) -{ return GstMessageType((unsigned)a|(unsigned)b); } -static GstSeekFlags operator|(const GstSeekFlags &a, const GstSeekFlags &b) -{ return GstSeekFlags((unsigned)a|(unsigned)b); } - -static void PrintErrMsg(const char *str, GstMessage *msg) -{ - GError *error; - gchar *debug; - - gst_message_parse_error(msg, &error, &debug); - Printf("%s: %s\n", str, error->message); - DPrintf("%s\n", debug); - - g_error_free(error); - g_free(debug); -} - -static GstCaps *SupportedBufferFormatCaps(int forcebits=0) -{ - GstStructure *structure; - GstCaps *caps; - - caps = gst_caps_new_empty(); - if(alIsExtensionPresent("AL_EXT_MCFORMATS")) - { - static const struct { - gint count; - GstAudioChannelPosition pos[8]; - } chans[] = { - { 1, - { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO } }, - { 2, - { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT } }, - { 4, - { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT } }, - { 6, - { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT } }, - { 7, - { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT } }, - { 8, - { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT } }, - }; - static const char *fmt32[] = { - "AL_FORMAT_MONO_FLOAT32", "AL_FORMAT_STEREO_FLOAT32", "AL_FORMAT_QUAD32", - "AL_FORMAT_51CHN32", "AL_FORMAT_61CHN32", "AL_FORMAT_71CHN32", NULL - }; - static const char *fmt16[] = { - "AL_FORMAT_MONO16", "AL_FORMAT_STEREO16", "AL_FORMAT_QUAD16", - "AL_FORMAT_51CHN16", "AL_FORMAT_61CHN16", "AL_FORMAT_71CHN16", NULL - }; - static const char *fmt8[] = { - "AL_FORMAT_MONO8", "AL_FORMAT_STEREO8", "AL_FORMAT_QUAD8", - "AL_FORMAT_51CHN8", "AL_FORMAT_61CHN8", "AL_FORMAT_71CHN8", NULL - }; - - if(alIsExtensionPresent("AL_EXT_FLOAT32")) - { - for(size_t i = 0;fmt32[i];i++) - { - if(forcebits && forcebits != 32) - break; - - ALenum val = alGetEnumValue(fmt32[i]); - if(getALError() != AL_NO_ERROR || val == 0 || val == -1) - continue; - - structure = gst_structure_new("audio/x-raw-float", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, NULL); - gst_structure_set(structure, "channels", G_TYPE_INT, - chans[i].count, NULL); - if(chans[i].count > 2) - gst_audio_set_channel_positions(structure, chans[i].pos); - gst_caps_append_structure(caps, structure); - } - } - for(size_t i = 0;fmt16[i];i++) - { - if(forcebits && forcebits != 16) - break; - - ALenum val = alGetEnumValue(fmt16[i]); - if(getALError() != AL_NO_ERROR || val == 0 || val == -1) - continue; - - structure = gst_structure_new("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - gst_structure_set(structure, "channels", G_TYPE_INT, - chans[i].count, NULL); - if(chans[i].count > 2) - gst_audio_set_channel_positions(structure, chans[i].pos); - gst_caps_append_structure(caps, structure); - } - for(size_t i = 0;fmt8[i];i++) - { - if(forcebits && forcebits != 8) - break; - - ALenum val = alGetEnumValue(fmt8[i]); - if(getALError() != AL_NO_ERROR || val == 0 || val == -1) - continue; - - structure = gst_structure_new("audio/x-raw-int", - "width", G_TYPE_INT, 8, - "depth", G_TYPE_INT, 8, - "signed", G_TYPE_BOOLEAN, FALSE, NULL); - gst_structure_set(structure, "channels", G_TYPE_INT, - chans[i].count, NULL); - if(chans[i].count > 2) - gst_audio_set_channel_positions(structure, chans[i].pos); - gst_caps_append_structure(caps, structure); - } - } - else - { - if(alIsExtensionPresent("AL_EXT_FLOAT32") && - (!forcebits || forcebits == 32)) - { - structure = gst_structure_new("audio/x-raw-float", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, - "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); - gst_caps_append_structure(caps, structure); - } - if(!forcebits || forcebits == 16) - { - structure = gst_structure_new("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "signed", G_TYPE_BOOLEAN, TRUE, - "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); - gst_caps_append_structure(caps, structure); - } - if(!forcebits || forcebits == 8) - { - structure = gst_structure_new("audio/x-raw-int", - "width", G_TYPE_INT, 8, - "depth", G_TYPE_INT, 8, - "signed", G_TYPE_BOOLEAN, FALSE, - "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); - gst_caps_append_structure(caps, structure); - } - } - return caps; -} - -class OpenALSoundStream : public SoundStream -{ - OpenALSoundRenderer *Renderer; - GstElement *gstPipeline; - GstTagList *TagList; - gint64 LoopPts[2]; - ALuint Source; - - bool Playing; - bool Looping; - - // Custom OpenAL sink; this is pretty crappy compared to the real - // openalsink element, but it gets the job done - static const ALsizei MaxSamplesQueued = 32768; - std::vector Buffers; - ALsizei SamplesQueued; - ALsizei SampleRate; - ALenum Format; - - static void sink_eos(GstAppSink *sink, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - if(!self->Playing) - return; - - ALint state; - do { - g_usleep(10000); - alGetSourcei(self->Source, AL_SOURCE_STATE, &state); - } while(getALError() == AL_NO_ERROR && state == AL_PLAYING && self->Playing); - - alSourceRewind(self->Source); - getALError(); - } - - static GstFlowReturn sink_preroll(GstAppSink *sink, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - // get the buffer from appsink - GstBuffer *buffer = gst_app_sink_pull_preroll(sink); - if(!buffer) return GST_FLOW_ERROR; - - GstCaps *caps = GST_BUFFER_CAPS(buffer); - gint bits = 0, channels = 0, rate = 0, i; - for(i = gst_caps_get_size(caps)-1;i >= 0;i--) - { - GstStructure *struc = gst_caps_get_structure(caps, i); - if(gst_structure_has_field(struc, "width")) - gst_structure_get_int(struc, "width", &bits); - if(gst_structure_has_field(struc, "channels")) - gst_structure_get_int(struc, "channels", &channels); - if(gst_structure_has_field(struc, "rate")) - gst_structure_get_int(struc, "rate", &rate); - } - - self->SampleRate = rate; - self->Format = FormatFromDesc(bits, channels); - - gst_buffer_unref(buffer); - if(self->Format == AL_NONE || self->SampleRate <= 0) - return GST_FLOW_ERROR; - return GST_FLOW_OK; - } - - static GstFlowReturn sink_buffer(GstAppSink *sink, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - GstBuffer *buffer = gst_app_sink_pull_buffer(sink); - if(!buffer) return GST_FLOW_ERROR; - - if(GST_BUFFER_SIZE(buffer) == 0) - { - gst_buffer_unref(buffer); - return GST_FLOW_OK; - } - - ALint processed, state; - next_buffer: - do { - alGetSourcei(self->Source, AL_SOURCE_STATE, &state); - alGetSourcei(self->Source, AL_BUFFERS_PROCESSED, &processed); - if(getALError() != AL_NO_ERROR) - { - gst_buffer_unref(buffer); - return GST_FLOW_ERROR; - } - if(processed > 0 || self->SamplesQueued < MaxSamplesQueued || - state != AL_PLAYING || !self->Playing) - break; - - g_usleep(10000); - } while(1); - - if(!self->Playing) - { - gst_buffer_unref(buffer); - return GST_FLOW_OK; - } - - ALuint bufID; - if(processed == 0) - { - alGenBuffers(1, &bufID); - if(getALError() != AL_NO_ERROR) - { - gst_buffer_unref(buffer); - return GST_FLOW_ERROR; - } - self->Buffers.push_back(bufID); - } - else while(1) - { - alSourceUnqueueBuffers(self->Source, 1, &bufID); - if(getALError() != AL_NO_ERROR) - { - gst_buffer_unref(buffer); - return GST_FLOW_ERROR; - } - - self->SamplesQueued -= getBufferLength(bufID); - processed--; - if(self->SamplesQueued < MaxSamplesQueued) - break; - if(processed == 0) - goto next_buffer; - self->Buffers.erase(find(self->Buffers.begin(), self->Buffers.end(), bufID)); - alDeleteBuffers(1, &bufID); - } - - alBufferData(bufID, self->Format, GST_BUFFER_DATA(buffer), - GST_BUFFER_SIZE(buffer), self->SampleRate); - alSourceQueueBuffers(self->Source, 1, &bufID); - gst_buffer_unref(buffer); - - if(getALError() != AL_NO_ERROR) - return GST_FLOW_ERROR; - - self->SamplesQueued += getBufferLength(bufID); - if(state != AL_PLAYING && processed == 0) - { - alSourcePlay(self->Source); - if(getALError() != AL_NO_ERROR) - return GST_FLOW_ERROR; - } - return GST_FLOW_OK; - } - - // Memory-based data source - std::vector MemData; - size_t MemDataPos; - - static void need_memdata(GstAppSrc *appsrc, guint size, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - if(self->MemDataPos >= self->MemData.size()) - { - gst_app_src_end_of_stream(appsrc); - return; - } - - // "read" the data it wants, up to the remaining amount - guint8 *data = &self->MemData[self->MemDataPos]; - size = std::min(size, self->MemData.size() - self->MemDataPos); - self->MemDataPos += size; - - GstBuffer *buffer = gst_buffer_new(); - GST_BUFFER_DATA(buffer) = data; - GST_BUFFER_SIZE(buffer) = size; - - // this takes ownership of the buffer; don't unref - gst_app_src_push_buffer(appsrc, buffer); - } - - static gboolean seek_memdata(GstAppSrc *appsrc, guint64 position, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - if(position > self->MemData.size()) - return FALSE; - self->MemDataPos = position; - return TRUE; - } - - static void memdata_source(GObject *object, GObject *orig, GParamSpec *pspec, OpenALSoundStream *self) - { - GstElement *elem; - g_object_get(self->gstPipeline, "source", &elem, NULL); - - GstAppSrc *appsrc = GST_APP_SRC(elem); - GstAppSrcCallbacks callbacks = { - need_memdata, NULL, seek_memdata - }; - gst_app_src_set_callbacks(appsrc, &callbacks, self, NULL); - gst_app_src_set_size(appsrc, self->MemData.size()); - gst_app_src_set_stream_type(appsrc, GST_APP_STREAM_TYPE_RANDOM_ACCESS); - - gst_object_unref(appsrc); - } - - // Callback-based data source - SoundStreamCallback Callback; - void *UserData; - int BufferBytes; - GstCaps *SrcCaps; - - static void need_callback(GstAppSrc *appsrc, guint size, gpointer user_data) - { - OpenALSoundStream *self = static_cast(user_data); - - GstBuffer *buffer; - if(!self->Playing) - buffer = gst_buffer_new_and_alloc(0); - else - { - buffer = gst_buffer_new_and_alloc(size); - if(!self->Callback(self, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer), self->UserData)) - { - gst_buffer_unref(buffer); - - gst_app_src_end_of_stream(appsrc); - return; - } - } - - gst_app_src_push_buffer(appsrc, buffer); - } - - static void callback_source(GObject *object, GObject *orig, GParamSpec *pspec, OpenALSoundStream *self) - { - GstElement *elem; - g_object_get(self->gstPipeline, "source", &elem, NULL); - - GstAppSrc *appsrc = GST_APP_SRC(elem); - GstAppSrcCallbacks callbacks = { - need_callback, NULL, NULL - }; - gst_app_src_set_callbacks(appsrc, &callbacks, self, NULL); - gst_app_src_set_size(appsrc, -1); - gst_app_src_set_max_bytes(appsrc, self->BufferBytes); - gst_app_src_set_stream_type(appsrc, GST_APP_STREAM_TYPE_STREAM); - gst_app_src_set_caps(appsrc, self->SrcCaps); - - gst_object_unref(appsrc); - } - - // General methods - virtual bool SetupSource() - { - // We don't actually use this source if we have an openalsink. However, - // holding on to it helps ensure we don't overrun our allotted voice - // count. - if(Renderer->FreeSfx.size() == 0) - { - FSoundChan *lowest = Renderer->FindLowestChannel(); - if(lowest) Renderer->StopChannel(lowest); - - if(Renderer->FreeSfx.size() == 0) - return false; - } - Source = Renderer->FreeSfx.back(); - Renderer->FreeSfx.pop_back(); - - alSource3f(Source, AL_DIRECTION, 0.f, 0.f, 0.f); - alSource3f(Source, AL_VELOCITY, 0.f, 0.f, 0.f); - alSource3f(Source, AL_POSITION, 0.f, 0.f, 0.f); - alSourcef(Source, AL_MAX_GAIN, 1.f); - alSourcef(Source, AL_GAIN, 1.f); - alSourcef(Source, AL_PITCH, 1.f); - alSourcef(Source, AL_ROLLOFF_FACTOR, 0.f); - alSourcef(Source, AL_SEC_OFFSET, 0.f); - alSourcei(Source, AL_SOURCE_RELATIVE, AL_TRUE); - alSourcei(Source, AL_LOOPING, AL_FALSE); - if(Renderer->EnvSlot) - { - alSourcef(Source, AL_ROOM_ROLLOFF_FACTOR, 0.f); - alSourcef(Source, AL_AIR_ABSORPTION_FACTOR, 0.f); - alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL); - alSource3i(Source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL); - } - - return (getALError() == AL_NO_ERROR); - } - - bool PipelineSetup() - { - TagList = gst_tag_list_new(); - g_return_val_if_fail(TagList != NULL, false); - - // Flags (can be combined): - // 0x01: video - Render the video stream - // 0x02: audio - Render the audio stream - // 0x04: text - Render subtitles - // 0x08: vis - Render visualisation when no video is present - // 0x10: soft-volume - Use software volume - // 0x20: native-audio - Only use native audio formats - // 0x40: native-video - Only use native video formats - // 0x80: download - Attempt progressive download buffering - int flags = 0x02 | 0x10; - - gstPipeline = gst_element_factory_make("playbin2", NULL); - g_return_val_if_fail(gstPipeline != NULL, false); - - GstElement *sink = gst_element_factory_make("openalsink", NULL); - if(sink != NULL) - { - // Give the sink our device, so it can create its own context and - // source to play with (and not risk cross-contaminating errors) - g_object_set(sink, "device-handle", Renderer->Device, NULL); - } - else - { - static bool warned = false; - if(!warned) - g_warning("Could not create an openalsink\n"); - warned = true; - - sink = gst_element_factory_make("appsink", NULL); - g_return_val_if_fail(sink != NULL, false); - - GstAppSink *appsink = GST_APP_SINK(sink); - GstAppSinkCallbacks callbacks = { - sink_eos, sink_preroll, sink_buffer, NULL - }; - GstCaps *caps = SupportedBufferFormatCaps(); - - gst_app_sink_set_callbacks(appsink, &callbacks, this, NULL); - gst_app_sink_set_drop(appsink, FALSE); - gst_app_sink_set_caps(appsink, caps); - gst_caps_unref(caps); - } - - // This takes ownership of the element; don't unref it - g_object_set(gstPipeline, "audio-sink", sink, NULL); - g_object_set(gstPipeline, "flags", flags, NULL); - return true; - } - - void HandleLoopTags() - { - // FIXME: Sample offsets assume a 44.1khz rate. Need to find some way - // to get the actual rate of the file from GStreamer - bool looppt_is_samples; - unsigned int looppt; - gchar *valstr; - - LoopPts[0] = 0; - if(gst_tag_list_get_string(TagList, "LOOP_START", &valstr)) - { - g_print("Got LOOP_START string: %s\n", valstr); - if(!S_ParseTimeTag(valstr, &looppt_is_samples, &looppt)) - Printf("Invalid LOOP_START tag: '%s'\n", valstr); - else - LoopPts[0] = (looppt_is_samples ? ((gint64)looppt*1000000000/44100) : - ((gint64)looppt*1000000)); - g_free(valstr); - } - LoopPts[1] = -1; - if(gst_tag_list_get_string(TagList, "LOOP_END", &valstr)) - { - g_print("Got LOOP_END string: %s\n", valstr); - if(!S_ParseTimeTag(valstr, &looppt_is_samples, &looppt)) - Printf("Invalid LOOP_END tag: '%s'\n", valstr); - else - { - LoopPts[1] = (looppt_is_samples ? ((gint64)looppt*1000000000/44100) : - ((gint64)looppt*1000000)); - if(LoopPts[1] <= LoopPts[0]) - LoopPts[1] = -1; - } - g_free(valstr); - } - } - - bool PreparePipeline() - { - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return false; - - GstStateChangeReturn ret = gst_element_set_state(gstPipeline, GST_STATE_PAUSED); - if(ret == GST_STATE_CHANGE_ASYNC) - { - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_TAG | GST_MESSAGE_ASYNC_DONE; - GstMessage *msg; - while((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) - { - PrintErrMsg("Prepare Error", msg); - ret = GST_STATE_CHANGE_FAILURE; - gst_message_unref(msg); - break; - } - else if(GST_MESSAGE_TYPE(msg) != GST_MESSAGE_TAG) - { - gst_message_unref(msg); - break; - } - - GstTagList *tags = NULL; - gst_message_parse_tag(msg, &tags); - - gst_tag_list_insert(TagList, tags, GST_TAG_MERGE_KEEP); - - gst_tag_list_free(tags); - gst_message_unref(msg); - } - } - else if(ret == GST_STATE_CHANGE_SUCCESS) - { - GstMessage *msg; - while((msg=gst_bus_pop(bus)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TAG) - { - GstTagList *tags = NULL; - gst_message_parse_tag(msg, &tags); - - gst_tag_list_insert(TagList, tags, GST_TAG_MERGE_KEEP); - - gst_tag_list_free(tags); - } - gst_message_unref(msg); - } - } - HandleLoopTags(); - - gst_object_unref(bus); - bus = NULL; - - return (ret != GST_STATE_CHANGE_FAILURE); - } - -public: - FTempFileName tmpfile; - ALfloat Volume; - - OpenALSoundStream(OpenALSoundRenderer *renderer) - : Renderer(renderer), gstPipeline(NULL), TagList(NULL), Source(0), - Playing(false), Looping(false), SamplesQueued(0), Callback(NULL), - UserData(NULL), BufferBytes(0), SrcCaps(NULL), Volume(1.0f) - { - LoopPts[0] = LoopPts[1] = 0; - Renderer->Streams.push_back(this); - } - - virtual ~OpenALSoundStream() - { - Playing = false; - - if(SrcCaps) - gst_caps_unref(SrcCaps); - SrcCaps = NULL; - - if(gstPipeline) - { - gst_element_set_state(gstPipeline, GST_STATE_NULL); - gst_object_unref(gstPipeline); - gstPipeline = NULL; - } - - if(TagList) - gst_tag_list_free(TagList); - TagList = NULL; - - if(Source) - { - alSourceRewind(Source); - alSourcei(Source, AL_BUFFER, 0); - - Renderer->FreeSfx.push_back(Source); - Source = 0; - } - - if(Buffers.size() > 0) - { - alDeleteBuffers(Buffers.size(), &Buffers[0]); - Buffers.clear(); - } - getALError(); - - Renderer->Streams.erase(find(Renderer->Streams.begin(), - Renderer->Streams.end(), this)); - Renderer = NULL; - } - - virtual bool Play(bool looping, float vol) - { - if(Playing) - return true; - - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return false; - - Looping = looping; - SetVolume(vol); - - if(Looping) - { - const GstSeekFlags flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT; - gst_element_seek(gstPipeline, 1.0, GST_FORMAT_TIME, flags, - GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_SET, LoopPts[1]); - } - - // Start playing the stream - Playing = true; - GstStateChangeReturn ret = gst_element_set_state(gstPipeline, GST_STATE_PLAYING); - if(ret == GST_STATE_CHANGE_FAILURE) - Playing = false; - if(ret == GST_STATE_CHANGE_ASYNC) - { - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE; - GstMessage *msg; - if((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) - { - PrintErrMsg("Play Error", msg); - Playing = false; - } - gst_message_unref(msg); - } - } - - gst_object_unref(bus); - bus = NULL; - - return Playing; - } - - virtual void Stop() - { - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return; - - // Stop the stream - GstStateChangeReturn ret = gst_element_set_state(gstPipeline, GST_STATE_PAUSED); - if(ret == GST_STATE_CHANGE_ASYNC) - { - Playing = false; - // Wait for the state change before requesting a seek - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE; - GstMessage *msg; - if((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) - PrintErrMsg("Stop Error", msg); - else if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ASYNC_DONE) - ret = GST_STATE_CHANGE_SUCCESS; - gst_message_unref(msg); - } - } - if(ret == GST_STATE_CHANGE_SUCCESS) - { - Playing = false; - - alSourceRewind(Source); - getALError(); - - const GstSeekFlags flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT; - gst_element_seek_simple(gstPipeline, GST_FORMAT_TIME, flags, 0); - } - - gst_object_unref(bus); - bus = NULL; - } - - virtual bool SetPaused(bool paused) - { - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return false; - - GstStateChangeReturn ret; - ret = gst_element_set_state(gstPipeline, (paused ? GST_STATE_PAUSED : GST_STATE_PLAYING)); - if(ret == GST_STATE_CHANGE_ASYNC) - { - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE; - GstMessage *msg; - if((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) - { - PrintErrMsg("Pause Error", msg); - ret = GST_STATE_CHANGE_FAILURE; - } - gst_message_unref(msg); - } - } - - if(ret != GST_STATE_CHANGE_FAILURE && paused) - { - alSourcePause(Source); - getALError(); - } - - gst_object_unref(bus); - bus = NULL; - - return (ret != GST_STATE_CHANGE_FAILURE); - } - - virtual void SetVolume(float vol) - { - Volume = vol; - g_object_set(gstPipeline, "volume", (double)(Volume*Renderer->MusicVolume), NULL); - } - - virtual unsigned int GetPosition() - { - GstFormat format = GST_FORMAT_TIME; - gint64 pos; - - // Position will be handled in milliseconds; GStreamer's time format is in nanoseconds - if(gst_element_query_position(gstPipeline, &format, &pos) && format == GST_FORMAT_TIME) - return (unsigned int)(pos / 1000000); - return 0; - } - - virtual bool SetPosition(unsigned int val) - { - gint64 pos = (gint64)val * 1000000; - return gst_element_seek_simple(gstPipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE, pos); - } - - virtual bool IsEnded() - { - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return true; - - GstMessage *msg; - while((msg=gst_bus_pop(bus)) != NULL) - { - switch(GST_MESSAGE_TYPE(msg)) - { - case GST_MESSAGE_SEGMENT_DONE: - case GST_MESSAGE_EOS: - Playing = false; - if(Looping) - Playing = gst_element_seek(gstPipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | - GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT, - GST_SEEK_TYPE_SET, LoopPts[0], - GST_SEEK_TYPE_SET, LoopPts[1]); - break; - - case GST_MESSAGE_ERROR: - PrintErrMsg("Pipeline Error", msg); - Playing = false; - break; - - case GST_MESSAGE_WARNING: - PrintErrMsg("Pipeline Warning", msg); - break; - - default: - break; - } - - gst_message_unref(msg); - } - - gst_object_unref(bus); - bus = NULL; - - return !Playing; - } - - bool Init(const char *filename) - { - if(!SetupSource() || !PipelineSetup()) - return false; - - GError *err = NULL; - gchar *uri; - if(g_path_is_absolute(filename)) - uri = g_filename_to_uri(filename, NULL, &err); - else if(g_strrstr(filename, "://") != NULL) - uri = g_strdup(filename); - else - { - gchar *curdir = g_get_current_dir(); - gchar *absolute_path = g_strconcat(curdir, G_DIR_SEPARATOR_S, filename, NULL); - uri = g_filename_to_uri(absolute_path, NULL, &err); - g_free(absolute_path); - g_free(curdir); - } - - if(!uri) - { - if(err) - { - Printf("Failed to convert "TEXTCOLOR_BOLD"%s"TEXTCOLOR_NORMAL" to URI: %s\n", - filename, err->message); - g_error_free(err); - } - return false; - } - - g_object_set(gstPipeline, "uri", uri, NULL); - g_free(uri); - - return PreparePipeline(); - } - - bool Init(const BYTE *data, unsigned int datalen) - { - // Can't keep the original pointer since the memory can apparently be - // overwritten at some point (happens with MIDI data, at least) - MemData.resize(datalen); - memcpy(&MemData[0], data, datalen); - MemDataPos = 0; - - if(!SetupSource() || !PipelineSetup()) - return false; - - g_object_set(gstPipeline, "uri", "appsrc://", NULL); - g_signal_connect(gstPipeline, "deep-notify::source", G_CALLBACK(memdata_source), this); - - return PreparePipeline(); - } - - bool Init(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) - { - Callback = callback; - UserData = userdata; - BufferBytes = buffbytes; - - GstStructure *structure; - if((flags&Float)) - structure = gst_structure_new("audio/x-raw-float", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, NULL); - else if((flags&Bits32)) - structure = gst_structure_new("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, - "depth", G_TYPE_INT, 32, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - else if((flags&Bits8)) - structure = gst_structure_new("audio/x-raw-int", - "width", G_TYPE_INT, 8, - "depth", G_TYPE_INT, 8, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - else - structure = gst_structure_new("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - gst_structure_set(structure, "channels", G_TYPE_INT, (flags&Mono)?1:2, NULL); - gst_structure_set(structure, "rate", G_TYPE_INT, samplerate, NULL); - - SrcCaps = gst_caps_new_full(structure, NULL); - - if(!SrcCaps || !SetupSource() || !PipelineSetup()) - return false; - - g_object_set(gstPipeline, "uri", "appsrc://", NULL); - g_signal_connect(gstPipeline, "deep-notify::source", G_CALLBACK(callback_source), this); - - return PreparePipeline(); - } -}; - - -class Decoder -{ - GstElement *gstPipeline, *gstSink; - GstTagList *TagList; - - const guint8 *MemData; - size_t MemDataSize; - size_t MemDataPos; - - static void need_memdata(GstAppSrc *appsrc, guint size, gpointer user_data) - { - Decoder *self = static_cast(user_data); - GstFlowReturn ret; - - if(self->MemDataPos >= self->MemDataSize) - { - gst_app_src_end_of_stream(appsrc); - return; - } - - const guint8 *data = &self->MemData[self->MemDataPos]; - size = (std::min)(size, (guint)(self->MemDataSize - self->MemDataPos)); - self->MemDataPos += size; - - GstBuffer *buffer = gst_buffer_new(); - GST_BUFFER_DATA(buffer) = const_cast(data); - GST_BUFFER_SIZE(buffer) = size; - - gst_app_src_push_buffer(appsrc, buffer); - } - - static gboolean seek_memdata(GstAppSrc *appsrc, guint64 position, gpointer user_data) - { - Decoder *self = static_cast(user_data); - - if(position > self->MemDataSize) - return FALSE; - self->MemDataPos = position; - return TRUE; - } - - static void memdata_source(GObject *object, GObject *orig, GParamSpec *pspec, Decoder *self) - { - GstElement *elem; - g_object_get(self->gstPipeline, "source", &elem, NULL); - - GstAppSrc *appsrc = GST_APP_SRC(elem); - GstAppSrcCallbacks callbacks = { - need_memdata, NULL, seek_memdata - }; - gst_app_src_set_callbacks(appsrc, &callbacks, self, NULL); - gst_app_src_set_size(appsrc, self->MemDataSize); - gst_app_src_set_stream_type(appsrc, GST_APP_STREAM_TYPE_RANDOM_ACCESS); - - gst_object_unref(appsrc); - } - - static GstFlowReturn sink_preroll(GstAppSink *sink, gpointer user_data) - { - Decoder *self = static_cast(user_data); - - GstBuffer *buffer = gst_app_sink_pull_preroll(sink); - if(!buffer) return GST_FLOW_ERROR; - - if(self->OutRate == 0) - { - GstCaps *caps = GST_BUFFER_CAPS(buffer); - - gint channels = 0, rate = 0, bits = 0, i; - for(i = gst_caps_get_size(caps)-1;i >= 0;i--) - { - GstStructure *struc = gst_caps_get_structure(caps, i); - if(gst_structure_has_field(struc, "channels")) - gst_structure_get_int(struc, "channels", &channels); - if(gst_structure_has_field(struc, "rate")) - gst_structure_get_int(struc, "rate", &rate); - if(gst_structure_has_field(struc, "width")) - gst_structure_get_int(struc, "width", &bits); - } - - self->OutChannels = channels; - self->OutBits = bits; - self->OutRate = rate; - } - - gst_buffer_unref(buffer); - if(self->OutRate <= 0) - return GST_FLOW_ERROR; - return GST_FLOW_OK; - } - - static GstFlowReturn sink_buffer(GstAppSink *sink, gpointer user_data) - { - Decoder *self = static_cast(user_data); - - GstBuffer *buffer = gst_app_sink_pull_buffer(sink); - if(!buffer) return GST_FLOW_ERROR; - - guint newsize = GST_BUFFER_SIZE(buffer); - size_t pos = self->OutData.size(); - self->OutData.resize(pos+newsize); - - memcpy(&self->OutData[pos], GST_BUFFER_DATA(buffer), newsize); - - gst_buffer_unref(buffer); - return GST_FLOW_OK; - } - - bool PipelineSetup(int forcebits) - { - if(forcebits && forcebits != 8 && forcebits != 16) - return false; - - TagList = gst_tag_list_new(); - g_return_val_if_fail(TagList != NULL, false); - - gstPipeline = gst_element_factory_make("playbin2", NULL); - g_return_val_if_fail(gstPipeline != NULL, false); - - gstSink = gst_element_factory_make("appsink", NULL); - g_return_val_if_fail(gstSink != NULL, false); - - GstAppSink *appsink = GST_APP_SINK(gstSink); - GstAppSinkCallbacks callbacks = { - NULL, sink_preroll, sink_buffer, NULL - }; - - GstCaps *caps = SupportedBufferFormatCaps(forcebits); - g_object_set(appsink, "sync", FALSE, NULL); - gst_app_sink_set_callbacks(appsink, &callbacks, this, NULL); - gst_app_sink_set_drop(appsink, FALSE); - gst_app_sink_set_caps(appsink, caps); - - g_object_set(gstPipeline, "audio-sink", gst_object_ref(gstSink), NULL); - g_object_set(gstPipeline, "flags", 0x02, NULL); - - gst_caps_unref(caps); - return true; - } - - void HandleLoopTags(unsigned int looppt[2], bool looppt_is_samples[2], bool has_looppt[2]) - { - gchar *valstr; - - if(gst_tag_list_get_string(TagList, "LOOP_START", &valstr)) - { - g_print("Got LOOP_START string: %s\n", valstr); - has_looppt[0] = S_ParseTimeTag(valstr, &looppt_is_samples[0], &looppt[0]); - if(!has_looppt[0]) - Printf("Invalid LOOP_START tag: '%s'\n", valstr); - g_free(valstr); - } - if(gst_tag_list_get_string(TagList, "LOOP_END", &valstr)) - { - g_print("Got LOOP_END string: %s\n", valstr); - has_looppt[1] = S_ParseTimeTag(valstr, &looppt_is_samples[1], &looppt[1]); - if(!has_looppt[1]) - Printf("Invalid LOOP_END tag: '%s'\n", valstr); - g_free(valstr); - } - } - -public: - std::vector OutData; - ALint LoopPts[2]; - ALsizei OutRate; - ALuint OutChannels; - ALuint OutBits; - - Decoder() - : gstPipeline(NULL), gstSink(NULL), TagList(NULL), - OutRate(0), OutChannels(0), OutBits(0) - { LoopPts[0] = LoopPts[1] = 0; } - - virtual ~Decoder() - { - if(gstSink) - gst_object_unref(gstSink); - gstSink = NULL; - - if(gstPipeline) - { - gst_element_set_state(gstPipeline, GST_STATE_NULL); - gst_object_unref(gstPipeline); - gstPipeline = NULL; - } - - if(TagList) - gst_tag_list_free(TagList); - TagList = NULL; - } - - bool Decode(const void *data, unsigned int datalen, int forcebits=0) - { - MemData = static_cast(data); - MemDataSize = datalen; - MemDataPos = 0; - OutData.clear(); - - if(!PipelineSetup(forcebits)) - return false; - - g_object_set(gstPipeline, "uri", "appsrc://", NULL); - g_signal_connect(gstPipeline, "deep-notify::source", G_CALLBACK(memdata_source), this); - - - GstBus *bus = gst_element_get_bus(gstPipeline); - if(!bus) return false; - GstMessage *msg; - - GstStateChangeReturn ret = gst_element_set_state(gstPipeline, GST_STATE_PLAYING); - if(ret == GST_STATE_CHANGE_ASYNC) - { - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_TAG | GST_MESSAGE_ASYNC_DONE; - while((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ASYNC_DONE) - { - ret = GST_STATE_CHANGE_SUCCESS; - break; - } - else if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TAG) - { - GstTagList *tags = NULL; - gst_message_parse_tag(msg, &tags); - - gst_tag_list_insert(TagList, tags, GST_TAG_MERGE_KEEP); - - gst_tag_list_free(tags); - } - else if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) - { - ret = GST_STATE_CHANGE_FAILURE; - PrintErrMsg("Decoder Error", msg); - break; - } - gst_message_unref(msg); - } - } - - bool err = true; - if(ret == GST_STATE_CHANGE_SUCCESS) - { - const GstMessageType types = GST_MESSAGE_ERROR | GST_MESSAGE_TAG | GST_MESSAGE_EOS; - while((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL) - { - if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_EOS) - { - err = false; - gst_message_unref(msg); - break; - } - if(GST_MESSAGE_TYPE(msg) != GST_MESSAGE_TAG) - { - PrintErrMsg("Decoder Error", msg); - gst_message_unref(msg); - break; - } - - GstTagList *tags = NULL; - gst_message_parse_tag(msg, &tags); - - gst_tag_list_insert(TagList, tags, GST_TAG_MERGE_KEEP); - - gst_tag_list_free(tags); - gst_message_unref(msg); - } - } - - if(!err) - { - ALuint FrameSize = OutChannels*OutBits/8; - if(OutData.size() >= FrameSize) - { - // HACK: Evilness abound. Seems GStreamer doesn't like (certain?) - // wave files and produces an extra sample, which can cause an - // audible click at the end. Cut it. - OutData.resize(OutData.size() - FrameSize); - } - - unsigned int looppt[2] = { 0, 0 }; - bool looppt_is_samples[2] = { true, true }; - bool has_looppt[2] = { false, false }; - - HandleLoopTags(looppt, looppt_is_samples, has_looppt); - if(has_looppt[0] || has_looppt[1]) - { - if(!has_looppt[0]) - LoopPts[0] = 0; - else if(looppt_is_samples[0]) - LoopPts[0] = (std::min)((ALint)looppt[0], - (ALint)(OutData.size() / FrameSize)); - else - LoopPts[0] = (std::min)((ALint)((gint64)looppt[0] * OutRate / 1000), - (ALint)(OutData.size() / FrameSize)); - - if(!has_looppt[1]) - LoopPts[1] = OutData.size() / FrameSize; - else if(looppt_is_samples[1]) - LoopPts[1] = (std::min)((ALint)looppt[1], - (ALint)(OutData.size() / FrameSize)); - else - LoopPts[1] = (std::min)((ALint)((gint64)looppt[1] * OutRate / 1000), - (ALint)(OutData.size() / FrameSize)); - } - } - - gst_object_unref(bus); - bus = NULL; - - return !err; - } -}; -#else /* WITH_GSTREAMER */ class OpenALSoundStream : public SoundStream { OpenALSoundRenderer *Renderer; @@ -1536,7 +274,6 @@ public: bool Decode(const void*, unsigned int, int=0) { return false; } }; -#endif /* WITH_GSTREAMER */ template @@ -1551,21 +288,6 @@ OpenALSoundRenderer::OpenALSoundRenderer() Printf("I_InitSound: Initializing OpenAL\n"); -#ifdef WITH_GSTREAMER - static bool GSTInited = false; - if(!GSTInited) - { - GError *error; - if(!gst_init_check(NULL, NULL, &error)) - { - Printf("Failed to initialize GStreamer: %s\n", error->message); - g_error_free(error); - return; - } - GSTInited = true; - } -#endif - if(snd_aldevice != "Default") { Device = alcOpenDevice(*snd_aldevice); diff --git a/src/sound/oalsound.h b/src/sound/oalsound.h index 96304db915..6df71914ad 100644 --- a/src/sound/oalsound.h +++ b/src/sound/oalsound.h @@ -11,16 +11,8 @@ #ifndef NO_OPENAL -#ifdef _WIN32 -#include -#include -#elif defined(__APPLE__) -#include -#include -#else -#include -#include -#endif +#include "al.h" +#include "alc.h" #ifndef ALC_ENUMERATE_ALL_EXT #define ALC_ENUMERATE_ALL_EXT 1