diff --git a/source/backend/engine/CarlaEngineJuce.cpp b/source/backend/engine/CarlaEngineJuce.cpp index 633a8f731..d286dce55 100644 --- a/source/backend/engine/CarlaEngineJuce.cpp +++ b/source/backend/engine/CarlaEngineJuce.cpp @@ -21,6 +21,7 @@ #include "CarlaEngineInternal.hpp" #include "CarlaBackendUtils.hpp" +#include "CarlaStringList.hpp" #include "RtLinkedList.hpp" @@ -37,23 +38,14 @@ CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Global static data -static const char** gRetNames = nullptr; -static OwnedArray gJuceDeviceTypes; +static CharStringListPtr gDeviceNames; +static OwnedArray gDeviceTypes; struct JuceCleanup : public DeletedAtShutdown { JuceCleanup() noexcept {} ~JuceCleanup() { - if (gRetNames != nullptr) - { - for (int i=0; gRetNames[i] != nullptr; ++i) - delete[] gRetNames[i]; - - delete[] gRetNames; - gRetNames = nullptr; - } - - gJuceDeviceTypes.clear(true); + gDeviceTypes.clear(true); } }; @@ -71,15 +63,16 @@ static void initJuceDevicesIfNeeded() needsInit = false; new JuceCleanup(); - sDeviceManager.createAudioDeviceTypes(gJuceDeviceTypes); + sDeviceManager.createAudioDeviceTypes(gDeviceTypes); // remove JACK from device list - for (int i=0, count=gJuceDeviceTypes.size(); i < count; ++i) + for (int i=0, count=gDeviceTypes.size(); i < count; ++i) { - if (gJuceDeviceTypes[i]->getTypeName() != "JACK") - continue; - - gJuceDeviceTypes.remove(i, true); + if (gDeviceTypes[i]->getTypeName() == "JACK") + { + gDeviceTypes.remove(i, true); + break; + } } } @@ -863,9 +856,9 @@ CarlaEngine* CarlaEngine::newJuce(const AudioApi api) AudioIODeviceType* deviceType = nullptr; - for (int i=0, count=gJuceDeviceTypes.size(); i < count; ++i) + for (int i=0, count=gDeviceTypes.size(); i < count; ++i) { - deviceType = gJuceDeviceTypes[i]; + deviceType = gDeviceTypes[i]; if (deviceType == nullptr || deviceType->getTypeName() == juceApi) break; @@ -883,7 +876,7 @@ uint CarlaEngine::getJuceApiCount() { initJuceDevicesIfNeeded(); - return static_cast(gJuceDeviceTypes.size()); + return static_cast(gDeviceTypes.size()); } const char* CarlaEngine::getJuceApiName(const uint uindex) @@ -892,9 +885,9 @@ const char* CarlaEngine::getJuceApiName(const uint uindex) const int index(static_cast(uindex)); - CARLA_SAFE_ASSERT_RETURN(index < gJuceDeviceTypes.size(), nullptr); + CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); - AudioIODeviceType* const deviceType(gJuceDeviceTypes[index]); + AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); return deviceType->getTypeName().toRawUTF8(); @@ -906,34 +899,27 @@ const char* const* CarlaEngine::getJuceApiDeviceNames(const uint uindex) const int index(static_cast(uindex)); - CARLA_SAFE_ASSERT_RETURN(index < gJuceDeviceTypes.size(), nullptr); + CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); - AudioIODeviceType* const deviceType(gJuceDeviceTypes[index]); + AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); deviceType->scanForDevices(); - StringArray deviceNames(deviceType->getDeviceNames()); - const int deviceNameCount(deviceNames.size()); + StringArray juceDeviceNames(deviceType->getDeviceNames()); + const int juceDeviceNameCount(juceDeviceNames.size()); - if (deviceNameCount <= 0) + if (juceDeviceNameCount <= 0) return nullptr; - if (gRetNames != nullptr) - { - for (int i=0; gRetNames[i] != nullptr; ++i) - delete[] gRetNames[i]; - delete[] gRetNames; - } - - gRetNames = new const char*[deviceNameCount+1]; + CarlaStringList devNames; - for (int i=0; i < deviceNameCount; ++i) - gRetNames[i] = carla_strdup(deviceNames[i].toRawUTF8()); + for (int i=0; i < juceDeviceNameCount; ++i) + devNames.append(juceDeviceNames[i].toRawUTF8()); - gRetNames[deviceNameCount] = nullptr; + gDeviceNames = devNames.toCharStringListPtr(); - return gRetNames; + return gDeviceNames; } const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint uindex, const char* const deviceName) @@ -942,9 +928,9 @@ const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint uindex, const int index(static_cast(uindex)); - CARLA_SAFE_ASSERT_RETURN(index < gJuceDeviceTypes.size(), nullptr); + CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr); - AudioIODeviceType* const deviceType(gJuceDeviceTypes[index]); + AudioIODeviceType* const deviceType(gDeviceTypes[index]); CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr); deviceType->scanForDevices(); diff --git a/source/backend/engine/CarlaEngineRtAudio.cpp b/source/backend/engine/CarlaEngineRtAudio.cpp index e30340ca9..c25bb590c 100644 --- a/source/backend/engine/CarlaEngineRtAudio.cpp +++ b/source/backend/engine/CarlaEngineRtAudio.cpp @@ -18,6 +18,7 @@ #include "CarlaEngineInternal.hpp" #include "CarlaBackendUtils.hpp" #include "CarlaMathUtils.hpp" +#include "CarlaStringList.hpp" #include "RtLinkedList.hpp" @@ -35,31 +36,13 @@ CARLA_BACKEND_START_NAMESPACE // ------------------------------------------------------------------------------------------------------------------- // Global static data -static const char** gRetNames = nullptr; +static CharStringListPtr gDeviceNames; static std::vector gRtAudioApis; -struct RtAudioCleanup { - RtAudioCleanup() noexcept {} - ~RtAudioCleanup() - { - if (gRetNames != nullptr) - { - for (int i=0; gRetNames[i] != nullptr; ++i) - delete[] gRetNames[i]; - - delete[] gRetNames; - gRetNames = nullptr; - } - - gRtAudioApis.clear(); - } -}; - // ------------------------------------------------------------------------------------------------------------------- static void initRtAudioAPIsIfNeeded() { - static const RtAudioCleanup sRtAudioCleanup; static bool needsInit = true; if (! needsInit) @@ -1114,39 +1097,19 @@ const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint index) if (devCount == 0) return nullptr; - LinkedList devNames; + CarlaStringList devNames; for (uint i=0; i < devCount; ++i) { RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i)); if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/) - devNames.append(carla_strdup(devInfo.name.c_str())); - } - - const size_t realDevCount(devNames.count()); - - if (gRetNames != nullptr) - { - for (int i=0; gRetNames[i] != nullptr; ++i) - delete[] gRetNames[i]; - delete[] gRetNames; - } - - gRetNames = new const char*[realDevCount+1]; - - for (size_t i=0; i < realDevCount; ++i) - { - gRetNames[i] = devNames.getAt(i, nullptr); - - if (gRetNames[i] == nullptr) - gRetNames[i] = carla_strdup("(unknown)"); + devNames.append(devInfo.name.c_str()); } - gRetNames[realDevCount] = nullptr; - devNames.clear(); + gDeviceNames = devNames.toCharStringListPtr(); - return gRetNames; + return gDeviceNames; } const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint index, const char* const deviceName) diff --git a/source/utils/CarlaStringList.hpp b/source/utils/CarlaStringList.hpp new file mode 100644 index 000000000..42950c008 --- /dev/null +++ b/source/utils/CarlaStringList.hpp @@ -0,0 +1,215 @@ +/* + * Carla String List + * Copyright (C) 2014 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#ifndef CARLA_STRING_LIST_HPP_INCLUDED +#define CARLA_STRING_LIST_HPP_INCLUDED + +#include "CarlaString.hpp" +#include "LinkedList.hpp" + +// ----------------------------------------------------------------------- +// Helper class to manage the lifetime of a "char**" object + +class CharStringListPtr +{ +public: + CharStringListPtr() noexcept + : charList(nullptr) {} + + CharStringListPtr(const char* const* const c) noexcept + : charList(c) {} + + CharStringListPtr(const CharStringListPtr& ptr) noexcept + : charList(nullptr) + { + copy(ptr.charList); + } + + CharStringListPtr(const LinkedList& list) noexcept + : charList(nullptr) + { + copy(list); + } + + ~CharStringListPtr() noexcept + { + clear(); + } + + operator const char* const*() const noexcept + { + return charList; + } + + CharStringListPtr& operator=(const char* const* const c) noexcept + { + clear(); + charList = c; + return *this; + } + + CharStringListPtr& operator=(const CharStringListPtr& ptr) + { + clear(); + copy(ptr.charList); + return *this; + } + + CharStringListPtr& operator=(const LinkedList& list) + { + clear(); + copy(list); + return *this; + } + +protected: + void clear() noexcept + { + if (charList == nullptr) + return; + + for (int i=0; charList[i] != nullptr; ++i) + delete[] charList[i]; + + delete[] charList; + charList = nullptr; + } + + void copy(const char* const* const c) noexcept + { + CARLA_SAFE_ASSERT_RETURN(c != nullptr,); + CARLA_SAFE_ASSERT_RETURN(charList == nullptr,); + + size_t count = 0; + for (; c[count] != nullptr; ++count) {} + CARLA_SAFE_ASSERT_RETURN(count > 0,); + + const char** tmpList; + + try { + tmpList = new const char*[count+1]; + } CARLA_SAFE_EXCEPTION_RETURN("CharStringListPtr::copy",); + + for (size_t i=0; i& list) noexcept + { + CARLA_SAFE_ASSERT_RETURN(charList == nullptr,); + + const size_t count(list.count()); + CARLA_SAFE_ASSERT_RETURN(count > 0,); + + const char** tmpList; + + try { + tmpList = new const char*[count+1]; + } CARLA_SAFE_EXCEPTION_RETURN("CharStringListPtr::copy",); + + size_t i=0; + for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next(), ++i) + { + const CarlaString& string(it.getValue()); + + try { + tmpList[i] = string.dup(); + } + catch(...) { + tmpList[i] = nullptr; + break; + } + } + + tmpList[count] = nullptr; + charList = tmpList; + } + +private: + const char* const* charList; +}; + +// ----------------------------------------------------------------------- +// CarlaStringList + +class CarlaStringList : public LinkedList +{ +public: + CarlaStringList() noexcept + : LinkedList(true) {} + +#if 0 + CarlaStringList(const CarlaStringList& list) noexcept + : LinkedList(true) + { + for (Itenerator it = list.begin(); it.valid(); it.next()) + LinkedList::append(it.getValue()); + } +#endif + + ~CarlaStringList() noexcept + { + clear(); + } + + bool append(const char* const strBuf) noexcept + { + const CarlaString string(strBuf); + return LinkedList::append(string); + } + + bool appendAt(const char* const strBuf, const Itenerator& it) noexcept + { + const CarlaString string(strBuf); + return LinkedList::appendAt(string, it); + } + + bool insert(const char* const strBuf) noexcept + { + const CarlaString string(strBuf); + return LinkedList::insert(string); + } + + bool insertAt(const char* const strBuf, const Itenerator& it) noexcept + { + const CarlaString string(strBuf); + return LinkedList::insertAt(string, it); + } + + CharStringListPtr toCharStringListPtr() const noexcept + { + return CharStringListPtr(*this); + } + +private: + LinkedList fList; +}; + +// ----------------------------------------------------------------------- + +#endif // CARLA_STRING_LIST_HPP_INCLUDED