Browse Source

Create StringList class for char** lifetime management, and use it

tags/1.9.4
falkTX 11 years ago
parent
commit
ff2fd75209
3 changed files with 249 additions and 85 deletions
  1. +28
    -42
      source/backend/engine/CarlaEngineJuce.cpp
  2. +6
    -43
      source/backend/engine/CarlaEngineRtAudio.cpp
  3. +215
    -0
      source/utils/CarlaStringList.hpp

+ 28
- 42
source/backend/engine/CarlaEngineJuce.cpp View File

@@ -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<AudioIODeviceType> gJuceDeviceTypes;
static CharStringListPtr gDeviceNames;
static OwnedArray<AudioIODeviceType> 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<uint>(gJuceDeviceTypes.size());
return static_cast<uint>(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<int>(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<int>(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<int>(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();


+ 6
- 43
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -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<RtAudio::Api> 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<const char*> 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)


+ 215
- 0
source/utils/CarlaStringList.hpp View File

@@ -0,0 +1,215 @@
/*
* Carla String List
* Copyright (C) 2014 Filipe Coelho <falktx@falktx.com>
*
* 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<CarlaString>& 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<CarlaString>& 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<count; ++i)
{
try {
tmpList[i] = carla_strdup(c[i]);
}
catch(...) {
tmpList[i] = nullptr;
break;
}
}

tmpList[count] = nullptr;
charList = tmpList;
}

void copy(const LinkedList<CarlaString>& 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<CarlaString>::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<CarlaString>
{
public:
CarlaStringList() noexcept
: LinkedList<CarlaString>(true) {}

#if 0
CarlaStringList(const CarlaStringList& list) noexcept
: LinkedList<CarlaString>(true)
{
for (Itenerator it = list.begin(); it.valid(); it.next())
LinkedList<CarlaString>::append(it.getValue());
}
#endif

~CarlaStringList() noexcept
{
clear();
}

bool append(const char* const strBuf) noexcept
{
const CarlaString string(strBuf);
return LinkedList<CarlaString>::append(string);
}

bool appendAt(const char* const strBuf, const Itenerator& it) noexcept
{
const CarlaString string(strBuf);
return LinkedList<CarlaString>::appendAt(string, it);
}

bool insert(const char* const strBuf) noexcept
{
const CarlaString string(strBuf);
return LinkedList<CarlaString>::insert(string);
}

bool insertAt(const char* const strBuf, const Itenerator& it) noexcept
{
const CarlaString string(strBuf);
return LinkedList<CarlaString>::insertAt(string, it);
}

CharStringListPtr toCharStringListPtr() const noexcept
{
return CharStringListPtr(*this);
}

private:
LinkedList<CarlaString> fList;
};

// -----------------------------------------------------------------------

#endif // CARLA_STRING_LIST_HPP_INCLUDED

Loading…
Cancel
Save