diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj
index a112b0454d..2ccb711ee5 100644
--- a/Source/Core/AudioCommon/AudioCommon.vcxproj
+++ b/Source/Core/AudioCommon/AudioCommon.vcxproj
@@ -38,6 +38,7 @@
+
@@ -54,6 +55,7 @@
+
diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters
index dfd38a0336..7c3fe389ee 100644
--- a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters
+++ b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters
@@ -8,6 +8,7 @@
+
@@ -30,6 +31,7 @@
+
diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt
index 5f0c7c143b..94eb45c9ed 100644
--- a/Source/Core/AudioCommon/CMakeLists.txt
+++ b/Source/Core/AudioCommon/CMakeLists.txt
@@ -1,6 +1,7 @@
set(SRCS
AudioCommon.cpp
CubebStream.cpp
+ CubebUtils.cpp
DPL2Decoder.cpp
Mixer.cpp
WaveFile.cpp
diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp
index 21bf6d812c..c9052e29c9 100644
--- a/Source/Core/AudioCommon/CubebStream.cpp
+++ b/Source/Core/AudioCommon/CubebStream.cpp
@@ -5,6 +5,7 @@
#include
#include "AudioCommon/CubebStream.h"
+#include "AudioCommon/CubebUtils.h"
#include "AudioCommon/DPL2Decoder.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
@@ -53,13 +54,9 @@ void CubebStream::StateCallback(cubeb_stream* stream, void* user_data, cubeb_sta
bool CubebStream::Start()
{
- if (cubeb_init(&m_ctx, "Dolphin", nullptr) != CUBEB_OK)
- {
- ERROR_LOG(AUDIO, "Error initializing cubeb library");
+ m_ctx = CubebUtils::GetContext();
+ if (!m_ctx)
return false;
- }
-
- INFO_LOG(AUDIO, "Cubeb initialized using %s backend", cubeb_get_backend_id(m_ctx));
m_stereo = !SConfig::GetInstance().bDPL2Decoder;
@@ -79,11 +76,11 @@ bool CubebStream::Start()
}
u32 minimum_latency = 0;
- if (cubeb_get_min_latency(m_ctx, params, &minimum_latency) != CUBEB_OK)
+ if (cubeb_get_min_latency(m_ctx.get(), params, &minimum_latency) != CUBEB_OK)
ERROR_LOG(AUDIO, "Error getting minimum latency");
INFO_LOG(AUDIO, "Minimum latency: %i frames", minimum_latency);
- if (cubeb_stream_init(m_ctx, &m_stream, "Dolphin Audio Output", nullptr, nullptr, nullptr,
+ if (cubeb_stream_init(m_ctx.get(), &m_stream, "Dolphin Audio Output", nullptr, nullptr, nullptr,
¶ms, std::max(BUFFER_SAMPLES, minimum_latency), DataCallback,
StateCallback, this) != CUBEB_OK)
{
@@ -106,7 +103,7 @@ void CubebStream::Stop()
ERROR_LOG(AUDIO, "Error stopping cubeb stream");
}
cubeb_stream_destroy(m_stream);
- cubeb_destroy(m_ctx);
+ m_ctx.reset();
}
void CubebStream::SetVolume(int volume)
diff --git a/Source/Core/AudioCommon/CubebStream.h b/Source/Core/AudioCommon/CubebStream.h
index 32434affd1..d0b153975e 100644
--- a/Source/Core/AudioCommon/CubebStream.h
+++ b/Source/Core/AudioCommon/CubebStream.h
@@ -20,7 +20,7 @@ public:
private:
bool m_stereo = false;
- cubeb* m_ctx = nullptr;
+ std::shared_ptr m_ctx;
cubeb_stream* m_stream = nullptr;
std::vector m_short_buffer;
diff --git a/Source/Core/AudioCommon/CubebUtils.cpp b/Source/Core/AudioCommon/CubebUtils.cpp
new file mode 100644
index 0000000000..07f4f530d6
--- /dev/null
+++ b/Source/Core/AudioCommon/CubebUtils.cpp
@@ -0,0 +1,75 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include
+#include
+#include
+
+#include "AudioCommon/CubebUtils.h"
+#include "Common/CommonPaths.h"
+#include "Common/Logging/Log.h"
+#include "Common/Logging/LogManager.h"
+#include "Common/StringUtil.h"
+
+#include
+
+static ptrdiff_t s_path_cutoff_point = 0;
+
+static void LogCallback(const char* format, ...)
+{
+ if (!LogManager::GetInstance())
+ return;
+
+ va_list args;
+ va_start(args, format);
+
+ const char* filename = va_arg(args, const char*) + s_path_cutoff_point;
+ int lineno = va_arg(args, int);
+ std::string adapted_format = StripSpaces(format + strlen("%s:%d:"));
+
+ LogManager::GetInstance()->LogWithFullPath(LogTypes::LNOTICE, LogTypes::AUDIO, filename, lineno,
+ adapted_format.c_str(), args);
+ va_end(args);
+}
+
+static void DestroyContext(cubeb* ctx)
+{
+ cubeb_destroy(ctx);
+ if (cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr) != CUBEB_OK)
+ {
+ ERROR_LOG(AUDIO, "Error removing cubeb log callback");
+ }
+}
+
+std::shared_ptr CubebUtils::GetContext()
+{
+ static std::weak_ptr weak;
+
+ std::shared_ptr shared = weak.lock();
+ // Already initialized
+ if (shared)
+ return shared;
+
+ const char* filename = __FILE__;
+ const char* match_point = strstr(filename, DIR_SEP "Source" DIR_SEP "Core" DIR_SEP);
+ if (match_point)
+ {
+ s_path_cutoff_point = match_point - filename + strlen(DIR_SEP "Externals" DIR_SEP);
+ }
+ if (cubeb_set_log_callback(CUBEB_LOG_NORMAL, LogCallback) != CUBEB_OK)
+ {
+ ERROR_LOG(AUDIO, "Error setting cubeb log callback");
+ }
+
+ cubeb* ctx;
+ if (cubeb_init(&ctx, "Dolphin", nullptr) != CUBEB_OK)
+ {
+ ERROR_LOG(AUDIO, "Error initializing cubeb library");
+ return nullptr;
+ }
+ INFO_LOG(AUDIO, "Cubeb initialized using %s backend", cubeb_get_backend_id(ctx));
+
+ weak = shared = {ctx, DestroyContext};
+ return shared;
+}
diff --git a/Source/Core/AudioCommon/CubebUtils.h b/Source/Core/AudioCommon/CubebUtils.h
new file mode 100644
index 0000000000..adf6c25484
--- /dev/null
+++ b/Source/Core/AudioCommon/CubebUtils.h
@@ -0,0 +1,14 @@
+// Copyright 2017 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+struct cubeb;
+
+namespace CubebUtils
+{
+std::shared_ptr GetContext();
+} // namespace CubebUtils
diff --git a/Source/Core/Common/Logging/LogManager.cpp b/Source/Core/Common/Logging/LogManager.cpp
index 18fd57fd43..3b2d925047 100644
--- a/Source/Core/Common/Logging/LogManager.cpp
+++ b/Source/Core/Common/Logging/LogManager.cpp
@@ -129,6 +129,12 @@ LogManager::~LogManager()
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file,
int line, const char* format, va_list args)
+{
+ return LogWithFullPath(level, type, file + m_path_cutoff_point, line, format, args);
+}
+
+void LogManager::LogWithFullPath(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
+ const char* file, int line, const char* format, va_list args)
{
char temp[MAX_MSGLEN];
LogContainer* log = m_Log[type];
@@ -138,10 +144,8 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const
CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
- const char* path_to_print = file + m_path_cutoff_point;
-
std::string msg = StringFromFormat(
- "%s %s:%u %c[%s]: %s\n", Common::Timer::GetTimeFormatted().c_str(), path_to_print, line,
+ "%s %s:%u %c[%s]: %s\n", Common::Timer::GetTimeFormatted().c_str(), file, line,
LogTypes::LOG_LEVEL_TO_CHAR[(int)level], log->GetShortName().c_str(), temp);
for (auto listener_id : *log)
diff --git a/Source/Core/Common/Logging/LogManager.h b/Source/Core/Common/Logging/LogManager.h
index ea7f2d86a3..0ec3c1f7de 100644
--- a/Source/Core/Common/Logging/LogManager.h
+++ b/Source/Core/Common/Logging/LogManager.h
@@ -96,6 +96,8 @@ public:
static u32 GetMaxLevel() { return MAX_LOGLEVEL; }
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file, int line,
const char* fmt, va_list args);
+ void LogWithFullPath(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char* file,
+ int line, const char* fmt, va_list args);
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
{
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
index 37f3b141bb..0ad3a263a3 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMic.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include "AudioCommon/CubebUtils.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
@@ -22,8 +23,7 @@ namespace ExpansionInterface
{
void CEXIMic::StreamInit()
{
- if (cubeb_init(&m_cubeb_ctx, "Dolphin", NULL) != CUBEB_OK)
- ERROR_LOG(EXPANSIONINTERFACE, "Error initializing cubeb library");
+ m_cubeb_ctx = CubebUtils::GetContext();
stream_buffer = nullptr;
samples_avail = stream_wpos = stream_rpos = 0;
@@ -32,12 +32,7 @@ void CEXIMic::StreamInit()
void CEXIMic::StreamTerminate()
{
StreamStop();
-
- if (m_cubeb_ctx)
- {
- cubeb_destroy(m_cubeb_ctx);
- m_cubeb_ctx = nullptr;
- }
+ m_cubeb_ctx.reset();
}
static void state_callback(cubeb_stream* stream, void* user_data, cubeb_state state)
@@ -84,12 +79,12 @@ void CEXIMic::StreamStart()
params.layout = CUBEB_LAYOUT_MONO;
u32 minimum_latency;
- if (cubeb_get_min_latency(m_cubeb_ctx, params, &minimum_latency) != CUBEB_OK)
+ if (cubeb_get_min_latency(m_cubeb_ctx.get(), params, &minimum_latency) != CUBEB_OK)
{
WARN_LOG(EXPANSIONINTERFACE, "Error getting minimum latency");
}
- if (cubeb_stream_init(m_cubeb_ctx, &m_cubeb_stream, "Dolphin Emulated GameCube Microphone",
+ if (cubeb_stream_init(m_cubeb_ctx.get(), &m_cubeb_stream, "Dolphin Emulated GameCube Microphone",
nullptr, ¶ms, nullptr, nullptr,
std::max(buff_size_samples, minimum_latency), data_callback,
state_callback, this) != CUBEB_OK)
diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMic.h b/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
index 7201edb35d..7f43798538 100644
--- a/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
+++ b/Source/Core/Core/HW/EXI/EXI_DeviceMic.h
@@ -69,7 +69,7 @@ private:
void UpdateNextInterruptTicks();
// Streaming input interface
- cubeb* m_cubeb_ctx = nullptr;
+ std::shared_ptr m_cubeb_ctx = nullptr;
cubeb_stream* m_cubeb_stream = nullptr;
void StreamLog(const char* msg);