Audaspace: porting changes from upstream.
authorJörg Müller <nexyon@gmail.com>
Thu, 17 Jan 2019 20:17:30 +0000 (21:17 +0100)
committerJörg Müller <nexyon@gmail.com>
Thu, 17 Jan 2019 20:17:30 +0000 (21:17 +0100)
- Silence some warnings.
- Fix: Python API memory leak.
- Fix for T54490: VSE breaks when I insert or remove headphones

extern/audaspace/bindings/C/AUD_Sound.cpp
extern/audaspace/bindings/python/PySound.cpp
extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
extern/audaspace/plugins/openal/OpenALDevice.cpp
extern/audaspace/plugins/openal/OpenALDevice.h
extern/audaspace/src/respec/ChannelMapperReader.cpp

index 30860ac..1f40f5c 100644 (file)
@@ -212,7 +212,7 @@ AUD_API const char* AUD_Sound_write(AUD_Sound* sound, const char* filename, AUD_
                std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, specs, static_cast<Container>(container), static_cast<Codec>(codec), bitrate);
                FileWriter::writeReader(reader, writer, 0, buffersize);
        }
-       catch(Exception& e)
+       catch(Exception&)
        {
                return "An exception occured while writing.";
        }
index 2ab1974..82c6036 100644 (file)
@@ -140,8 +140,6 @@ Sound_data(Sound* self)
 
        std::memcpy(data, buffer->getBuffer(), buffer->getSize());
 
-       Py_INCREF(array);
-
        return reinterpret_cast<PyObject*>(array);
 }
 
index 09b7089..2cd3261 100644 (file)
@@ -261,6 +261,8 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
        case CHANNELS_SURROUND71:
                channel_layout = AV_CH_LAYOUT_7POINT1;
                break;
+       default:
+               AUD_THROW(FileException, "File couldn't be written, channel layout not supported.");
        }
 
        try
index 2a60978..6ad87c1 100644 (file)
@@ -61,10 +61,58 @@ bool OpenALDevice::OpenALHandle::pause(bool keep)
        return false;
 }
 
+bool OpenALDevice::OpenALHandle::reinitialize()
+{
+       DeviceSpecs specs = m_device->m_specs;
+       specs.specs = m_reader->getSpecs();
+
+       ALenum format;
+
+       if(!m_device->getFormat(format, specs.specs))
+               return true;
+
+       m_format = format;
+
+       // OpenAL playback code
+       alGenBuffers(CYCLE_BUFFERS, m_buffers);
+       if(alGetError() != AL_NO_ERROR)
+               return true;
+
+       m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+       int length;
+       bool eos;
+
+       for(m_current = 0; m_current < CYCLE_BUFFERS; m_current++)
+       {
+               length = m_device->m_buffersize;
+               m_reader->read(length, eos, m_device->m_buffer.getBuffer());
+
+               if(length == 0)
+                       break;
+
+               alBufferData(m_buffers[m_current], m_format, m_device->m_buffer.getBuffer(), length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
+
+               if(alGetError() != AL_NO_ERROR)
+                       return true;
+       }
+
+       alGenSources(1, &m_source);
+       if(alGetError() != AL_NO_ERROR)
+               return true;
+
+       alSourceQueueBuffers(m_source, m_current, m_buffers);
+       if(alGetError() != AL_NO_ERROR)
+               return true;
+
+       alSourcei(m_source, AL_SOURCE_RELATIVE, m_relative);
+
+       return false;
+}
+
 OpenALDevice::OpenALHandle::OpenALHandle(OpenALDevice* device, ALenum format, std::shared_ptr<IReader> reader, bool keep) :
        m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format),
        m_eos(false), m_loopcount(0), m_stop(nullptr), m_stop_data(nullptr), m_status(STATUS_PLAYING),
-       m_device(device)
+       m_relative(1), m_device(device)
 {
        DeviceSpecs specs = m_device->m_specs;
        specs.specs = m_reader->getSpecs();
@@ -162,6 +210,9 @@ bool OpenALDevice::OpenALHandle::stop()
        if(!m_status)
                return false;
 
+       if(m_stop)
+               m_stop(m_stop_data);
+
        m_status = STATUS_INVALID;
 
        alDeleteSources(1, &m_source);
@@ -525,8 +576,6 @@ bool OpenALDevice::OpenALHandle::setOrientation(const Quaternion& orientation)
 
 bool OpenALDevice::OpenALHandle::isRelative()
 {
-       int result;
-
        if(!m_status)
                return false;
 
@@ -535,9 +584,9 @@ bool OpenALDevice::OpenALHandle::isRelative()
        if(!m_status)
                return false;
 
-       alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
+       alGetSourcei(m_source, AL_SOURCE_RELATIVE, &m_relative);
 
-       return result;
+       return m_relative;
 }
 
 bool OpenALDevice::OpenALHandle::setRelative(bool relative)
@@ -550,7 +599,9 @@ bool OpenALDevice::OpenALHandle::setRelative(bool relative)
        if(!m_status)
                return false;
 
-       alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
+       m_relative = relative;
+
+       alSourcei(m_source, AL_SOURCE_RELATIVE, m_relative);
 
        return true;
 }
@@ -852,6 +903,80 @@ void OpenALDevice::updateStreams()
        {
                lock();
 
+               if(m_checkDisconnect)
+               {
+                       ALCint connected;
+                       alcGetIntegerv(m_device, alcGetEnumValue(m_device, "ALC_CONNECTED"), 1, &connected);
+
+                       if(!connected)
+                       {
+                               // quit OpenAL
+                               alcMakeContextCurrent(nullptr);
+                               alcDestroyContext(m_context);
+                               alcCloseDevice(m_device);
+
+                               // restart
+                               if(m_name.empty())
+                                       m_device = alcOpenDevice(nullptr);
+                               else
+                                       m_device = alcOpenDevice(m_name.c_str());
+
+                               // if device opening failed, there's really nothing we can do
+                               if(m_device)
+                               {
+                                       // at least try to set the frequency
+
+                                       ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
+                                       ALCint* attributes = attribs;
+                                       if(specs.rate == RATE_INVALID)
+                                               attributes = nullptr;
+
+                                       m_context = alcCreateContext(m_device, attributes);
+                                       alcMakeContextCurrent(m_context);
+
+                                       m_checkDisconnect = alcIsExtensionPresent(m_device, "ALC_EXT_disconnect");
+
+                                       alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
+
+                                       // check for specific formats and channel counts to be played back
+                                       if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
+                                               specs.format = FORMAT_FLOAT32;
+                                       else
+                                               specs.format = FORMAT_S16;
+
+                                       // if the format of the device changed, all handles are invalidated
+                                       // this is unlikely to happen though
+                                       if(specs.format != m_specs.format)
+                                               stopAll();
+
+                                       m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
+
+                                       if((!m_useMC && specs.channels > CHANNELS_STEREO) ||
+                                                       specs.channels == CHANNELS_STEREO_LFE ||
+                                                       specs.channels == CHANNELS_SURROUND5)
+                                               specs.channels = CHANNELS_STEREO;
+
+                                       alGetError();
+                                       alcGetError(m_device);
+
+                                       m_specs = specs;
+
+                                       std::list<std::shared_ptr<OpenALHandle> > stopSounds;
+
+                                       for(auto& handle : m_playingSounds)
+                                               if(handle->reinitialize())
+                                                       stopSounds.push_back(handle);
+
+                                       for(auto& handle : m_pausedSounds)
+                                               if(handle->reinitialize())
+                                                       stopSounds.push_back(handle);
+
+                                       for(auto& sound : stopSounds)
+                                               sound->stop();
+                               }
+                       }
+               }
+
                alcSuspendContext(m_context);
                cerr = alcGetError(m_device);
                if(cerr == ALC_NO_ERROR)
@@ -957,12 +1082,14 @@ void OpenALDevice::updateStreams()
                                        // if it really stopped
                                        if(sound->m_eos && info != AL_INITIAL)
                                        {
-                                               if(sound->m_stop)
-                                                       sound->m_stop(sound->m_stop_data);
-
                                                // pause or
                                                if(sound->m_keep)
+                                               {
+                                                       if(sound->m_stop)
+                                                               sound->m_stop(sound->m_stop_data);
+
                                                        pauseSounds.push_back(sound);
+                                               }
                                                // stop
                                                else
                                                        stopSounds.push_back(sound);
@@ -1005,16 +1132,16 @@ void OpenALDevice::updateStreams()
 /******************************************************************************/
 
 OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name) :
-       m_playing(false), m_buffersize(buffersize)
+       m_name(name), m_playing(false), m_buffersize(buffersize)
 {
        // cannot determine how many channels or which format OpenAL uses, but
        // it at least is able to play 16 bit stereo audio
        specs.format = FORMAT_S16;
 
-       if(name.empty())
+       if(m_name.empty())
                m_device = alcOpenDevice(nullptr);
        else
-               m_device = alcOpenDevice(name.c_str());
+               m_device = alcOpenDevice(m_name.c_str());
 
        if(!m_device)
                AUD_THROW(DeviceException, "The audio device couldn't be opened with OpenAL.");
@@ -1028,6 +1155,8 @@ OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name)
        m_context = alcCreateContext(m_device, attributes);
        alcMakeContextCurrent(m_context);
 
+       m_checkDisconnect = alcIsExtensionPresent(m_device, "ALC_EXT_disconnect");
+
        alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
 
        // check for specific formats and channel counts to be played back
index b9b461a..c2bec44 100644 (file)
@@ -95,11 +95,16 @@ private:
                /// Current status of the handle
                Status m_status;
 
+               /// Whether the source is relative or not.
+               ALint m_relative;
+
                /// Own device.
                OpenALDevice* m_device;
 
                AUD_LOCAL bool pause(bool keep);
 
+               AUD_LOCAL bool reinitialize();
+
                // delete copy constructor and operator=
                OpenALHandle(const OpenALHandle&) = delete;
                OpenALHandle& operator=(const OpenALHandle&) = delete;
@@ -173,11 +178,21 @@ private:
         */
        DeviceSpecs m_specs;
 
+       /**
+        * The device name.
+        */
+       std::string m_name;
+
        /**
         * Whether the device has the AL_EXT_MCFORMATS extension.
         */
        bool m_useMC;
 
+       /**
+        * Whether the ALC_EXT_disconnect extension is present and device disconnect should be checked repeatedly.
+        */
+       bool m_checkDisconnect;
+
        /**
         * The list of sounds that are currently playing.
         */
index 850e54b..1af5e70 100644 (file)
@@ -296,72 +296,77 @@ const Channel* ChannelMapperReader::CHANNEL_MAPS[] =
        ChannelMapperReader::SURROUND71_MAP
 };
 
+constexpr float deg2rad(double angle)
+{
+       return float(angle * M_PI / 180.0);
+}
+
 const float ChannelMapperReader::MONO_ANGLES[] =
 {
-       0.0f * M_PI / 180.0f
+       deg2rad(0.0)
 };
 
 const float ChannelMapperReader::STEREO_ANGLES[] =
 {
-       -90.0f * M_PI / 180.0f,
-        90.0f * M_PI / 180.0f
+       deg2rad(-90.0),
+       deg2rad( 90.0)
 };
 
 const float ChannelMapperReader::STEREO_LFE_ANGLES[] =
 {
-       -90.0f * M_PI / 180.0f,
-        90.0f * M_PI / 180.0f,
-         0.0f * M_PI / 180.0f
+       deg2rad(-90.0),
+       deg2rad( 90.0),
+       deg2rad(  0.0)
 };
 
 const float ChannelMapperReader::SURROUND4_ANGLES[] =
 {
-        -45.0f * M_PI / 180.0f,
-         45.0f * M_PI / 180.0f,
-       -135.0f * M_PI / 180.0f,
-        135.0f * M_PI / 180.0f
+       deg2rad( -45.0),
+       deg2rad(  45.0),
+       deg2rad(-135.0),
+       deg2rad( 135.0)
 };
 
 const float ChannelMapperReader::SURROUND5_ANGLES[] =
 {
-        -30.0f * M_PI / 180.0f,
-         30.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-       -110.0f * M_PI / 180.0f,
-        110.0f * M_PI / 180.0f
+       deg2rad( -30.0),
+       deg2rad(  30.0),
+       deg2rad(   0.0),
+       deg2rad(-110.0),
+       deg2rad( 110.0)
 };
 
 const float ChannelMapperReader::SURROUND51_ANGLES[] =
 {
-         -30.0f * M_PI / 180.0f,
-          30.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-       -110.0f * M_PI / 180.0f,
-        110.0f * M_PI / 180.0f
+       deg2rad( -30.0),
+       deg2rad(  30.0),
+       deg2rad(   0.0),
+       deg2rad(   0.0),
+       deg2rad(-110.0),
+       deg2rad( 110.0)
 };
 
 const float ChannelMapperReader::SURROUND61_ANGLES[] =
 {
-         -30.0f * M_PI / 180.0f,
-          30.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-        180.0f * M_PI / 180.0f,
-       -110.0f * M_PI / 180.0f,
-        110.0f * M_PI / 180.0f
+       deg2rad( -30.0),
+       deg2rad(  30.0),
+       deg2rad(   0.0),
+       deg2rad(   0.0),
+       deg2rad( 180.0),
+       deg2rad(-110.0),
+       deg2rad( 110.0)
 };
 
 const float ChannelMapperReader::SURROUND71_ANGLES[] =
 {
-         -30.0f * M_PI / 180.0f,
-          30.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-          0.0f * M_PI / 180.0f,
-       -110.0f * M_PI / 180.0f,
-        110.0f * M_PI / 180.0f,
-       -150.0f * M_PI / 180.0f,
-        150.0f * M_PI / 180.0f
+       deg2rad( -30.0),
+       deg2rad(  30.0),
+       deg2rad(   0.0),
+       deg2rad(   0.0),
+       deg2rad(-110.0),
+       deg2rad( 110.0),
+       deg2rad(-150.0),
+       deg2rad( 150.0)
 };
 
 const float* ChannelMapperReader::CHANNEL_ANGLES[] =