Added a new IDebug interface to the SDK -- plugins can opt-in to get an instance to one of these and write debug information to the standard location, just like the rest of the app.

This commit is contained in:
casey langen 2018-12-26 22:53:53 -08:00
parent 1b4b9127c4
commit cc134775ef
12 changed files with 140 additions and 8 deletions

View File

@ -10,6 +10,7 @@ musikcube:
* added the ability to customize the key used to quit the app. it is currently * added the ability to customize the key used to quit the app. it is currently
not exposed in the ui, but it can be changed by editing not exposed in the ui, but it can be changed by editing
`~/.musikcube/settings.json` and updating the `AppQuitKey`. `~/.musikcube/settings.json` and updating the `AppQuitKey`.
* scrapped and re-implemented the debug log viewer, accessible via `ctrl+~`
* added feodra 29 support (dvdmuckle) * added feodra 29 support (dvdmuckle)
* fixed configuration script bugs that were causing breakage in FreeBSD * fixed configuration script bugs that were causing breakage in FreeBSD
* migrated to non-bundled `taglib` for macOS and most Linux distributions * migrated to non-bundled `taglib` for macOS and most Linux distributions
@ -19,6 +20,10 @@ musikcube:
musikdroid: musikdroid:
* updated to compile against the latest tooling * updated to compile against the latest tooling
sdk:
* added a new `IDebug` interface plugins can request via `SetDebug` to write
log information to the standard location, just like the rest of the app.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
0.51.0 0.51.0

View File

@ -99,11 +99,8 @@ void GaplessTransport::PrepareNextTrack(const std::string& uri, Gain gain) {
} }
void GaplessTransport::Start(const std::string& uri, Gain gain, StartMode mode) { void GaplessTransport::Start(const std::string& uri, Gain gain, StartMode mode) {
musik::debug::info(TAG, "we were asked to start the track at " + uri); musik::debug::info(TAG, "starting track at " + uri);
Player* newPlayer = Player::Create(uri, this->output, Player::NoDrain, this, gain); Player* newPlayer = Player::Create(uri, this->output, Player::NoDrain, this, gain);
musik::debug::info(TAG, "Player created successfully");
this->StartWithPlayer(newPlayer, mode); this->StartWithPlayer(newPlayer, mode);
} }

View File

@ -118,7 +118,7 @@ namespace musik { namespace core { namespace audio {
return nullptr; return nullptr;
} }
musik::debug::info(TAG, "about ready to play: " + uri); musik::debug::info(TAG, "found a decoder for " + uri);
return decoder; return decoder;
} }

View File

@ -92,7 +92,6 @@ bool LocalFileStream::Open(const char *filename, unsigned int options) {
#endif #endif
if (this->file.load()) { if (this->file.load()) {
debug::info(TAG, "opened successfully");
return true; return true;
} }
} }

View File

@ -39,6 +39,7 @@
#include <core/support/Common.h> #include <core/support/Common.h>
#include <core/support/Preferences.h> #include <core/support/Preferences.h>
#include <core/debug.h>
#include <core/io/DataStreamFactory.h> #include <core/io/DataStreamFactory.h>
#include <core/audio/Buffer.h> #include <core/audio/Buffer.h>
#include <core/audio/Streams.h> #include <core/audio/Streams.h>
@ -49,6 +50,7 @@
#include <core/runtime/Message.h> #include <core/runtime/Message.h>
#include <core/support/Messages.h> #include <core/support/Messages.h>
#include <core/sdk/IDebug.h>
#include <core/sdk/IIndexerNotifier.h> #include <core/sdk/IIndexerNotifier.h>
#include <core/sdk/IEnvironment.h> #include <core/sdk/IEnvironment.h>
@ -60,6 +62,7 @@ using namespace musik::core::runtime;
using namespace musik::core::sdk; using namespace musik::core::sdk;
typedef void(*SetEnvironment)(IEnvironment*); typedef void(*SetEnvironment)(IEnvironment*);
typedef void(*SetDebug)(IDebug*);
typedef void(*SetSimpleDataProvider)(ISimpleDataProvider*); typedef void(*SetSimpleDataProvider)(ISimpleDataProvider*);
typedef void(*SetIndexerNotifier)(IIndexerNotifier*); typedef void(*SetIndexerNotifier)(IIndexerNotifier*);
@ -79,7 +82,26 @@ static void saveEnvironment() {
} }
} }
static class Environment : public IEnvironment { static class Debug: public IDebug {
public:
virtual void Verbose(const char* tag, const char* message) override {
musik::debug::verbose(tag, message);
}
virtual void Info(const char* tag, const char* message) override {
musik::debug::info(tag, message);
}
virtual void Warning(const char* tag, const char* message) override {
musik::debug::warning(tag, message);
}
virtual void Error(const char* tag, const char* message) override {
musik::debug::error(tag, message);
}
} debugger;
static class Environment: public IEnvironment {
public: public:
virtual size_t GetPath(PathType type, char* dst, int size) override { virtual size_t GetPath(PathType type, char* dst, int size) override {
std::string path; std::string path;
@ -110,6 +132,10 @@ static class Environment : public IEnvironment {
return streams::GetEncoderForType(type); return streams::GetEncoderForType(type);
} }
virtual IDebug* GetDebug() override {
return &debugger;
}
virtual IPreferences* GetPreferences(const char* name) override { virtual IPreferences* GetPreferences(const char* name) override {
return Preferences::Unmanaged(name ? name : std::string()); return Preferences::Unmanaged(name ? name : std::string());
} }
@ -266,6 +292,13 @@ namespace musik { namespace core { namespace plugin {
[](musik::core::sdk::IPlugin* plugin, SetEnvironment func) { [](musik::core::sdk::IPlugin* plugin, SetEnvironment func) {
func(&environment); func(&environment);
}); });
/* debug */
PluginFactory::Instance().QueryFunction<SetDebug>(
"SetDebug",
[](musik::core::sdk::IPlugin* plugin, SetDebug func) {
func(&debugger);
});
} }
void UninstallDependencies() { void UninstallDependencies() {
@ -299,6 +332,13 @@ namespace musik { namespace core { namespace plugin {
[](musik::core::sdk::IPlugin* plugin, SetEnvironment func) { [](musik::core::sdk::IPlugin* plugin, SetEnvironment func) {
func(nullptr); func(nullptr);
}); });
/* debug */
PluginFactory::Instance().QueryFunction<SetDebug>(
"SetDebug",
[](musik::core::sdk::IPlugin* plugin, SetDebug func) {
func(nullptr);
});
} }
} } } } } }

47
src/core/sdk/IDebug.h Normal file
View File

@ -0,0 +1,47 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2017 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
namespace musik { namespace core { namespace sdk {
class IDebug {
public:
virtual void Verbose(const char* tag, const char* message) = 0;
virtual void Info(const char* tag, const char* message) = 0;
virtual void Warning(const char* tag, const char* message) = 0;
virtual void Error(const char* tag, const char* message) = 0;
};
} } }

View File

@ -41,6 +41,7 @@
#include "IPreferences.h" #include "IPreferences.h"
#include "IOutput.h" #include "IOutput.h"
#include "ITrackList.h" #include "ITrackList.h"
#include "IDebug.h"
namespace musik { namespace core { namespace sdk { namespace musik { namespace core { namespace sdk {
@ -52,6 +53,7 @@ namespace musik { namespace core { namespace sdk {
virtual IEncoder* GetEncoder(const char* type) = 0; virtual IEncoder* GetEncoder(const char* type) = 0;
virtual IBuffer* GetBuffer(size_t samples, size_t rate = 44100, size_t channels = 2) = 0; virtual IBuffer* GetBuffer(size_t samples, size_t rate = 44100, size_t channels = 2) = 0;
virtual IPreferences* GetPreferences(const char* name) = 0; virtual IPreferences* GetPreferences(const char* name) = 0;
virtual IDebug* GetDebug() = 0;
virtual size_t GetOutputCount() = 0; virtual size_t GetOutputCount() = 0;
virtual IOutput* GetOutputAtIndex(size_t index) = 0; virtual IOutput* GetOutputAtIndex(size_t index) = 0;
virtual IOutput* GetOutputWithName(const char* name) = 0; virtual IOutput* GetOutputWithName(const char* name) = 0;

View File

@ -6,6 +6,7 @@
#include <cursespp/ToastOverlay.h> #include <cursespp/ToastOverlay.h>
#include <app/util/Hotkeys.h> #include <app/util/Hotkeys.h>
#include <app/util/Messages.h> #include <app/util/Messages.h>
#include <app/version.h>
using namespace musik::cube; using namespace musik::cube;
using namespace musik::core; using namespace musik::core;
@ -55,6 +56,18 @@ void ConsoleLayout::OnItemActivated(cursespp::ListWindow* window, size_t index)
ToastOverlay::Show(this->logger->Adapter()->StringAt(index), -1); ToastOverlay::Show(this->logger->Adapter()->StringAt(index), -1);
} }
bool ConsoleLayout::KeyPress(const std::string& kn) {
if (kn == "^_") { /* ctrl+/ */
ToastOverlay::Show(u8fmt(_TSTR("console_version"), VERSION), -1);
return true;
}
else if (kn == "x") {
this->adapter->Clear();
return true;
}
return LayoutBase::KeyPress(kn);
}
void ConsoleLayout::SetShortcutsWindow(ShortcutsWindow* shortcuts) { void ConsoleLayout::SetShortcutsWindow(ShortcutsWindow* shortcuts) {
if (shortcuts) { if (shortcuts) {
shortcuts->AddShortcut(Hotkeys::Get(Hotkeys::NavigateConsole), _TSTR("shortcuts_console")); shortcuts->AddShortcut(Hotkeys::Get(Hotkeys::NavigateConsole), _TSTR("shortcuts_console"));

View File

@ -17,6 +17,7 @@ namespace musik { namespace cube {
virtual void OnLayout() override; virtual void OnLayout() override;
virtual void SetShortcutsWindow(cursespp::ShortcutsWindow* w) override; virtual void SetShortcutsWindow(cursespp::ShortcutsWindow* w) override;
virtual bool KeyPress(const std::string& kn) override;
protected: protected:
void OnVisibilityChanged(bool visible) override; void OnVisibilityChanged(bool visible) override;

View File

@ -36,6 +36,7 @@
"browse_no_subdirectories_toast": "there are no more sub-directories.\n\npress '%s' to play the selection.", "browse_no_subdirectories_toast": "there are no more sub-directories.\n\npress '%s' to play the selection.",
"console_list_title": "debug logs", "console_list_title": "debug logs",
"console_version": "musikcube version %s",
"hotkeys_title": "key bindings", "hotkeys_title": "key bindings",
"hotkeys_reset_defaults": "reset all", "hotkeys_reset_defaults": "reset all",

View File

@ -33,13 +33,27 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#include "FfmpegDecoder.h" #include "FfmpegDecoder.h"
#include <core/sdk/IDebug.h>
#include <algorithm> #include <algorithm>
#ifdef WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
#define BUFFER_SIZE 4096 #define BUFFER_SIZE 4096
#define PROBE_SIZE 32768 #define PROBE_SIZE 32768
using namespace musik::core::sdk; using namespace musik::core::sdk;
static const char* TAG = "ffmpegdecoder";
static IDebug* debug = nullptr;
extern "C" DLLEXPORT void SetDebug(IDebug* debug) {
::debug = debug;
}
static int readCallback(void* opaque, uint8_t* buffer, int bufferSize) { static int readCallback(void* opaque, uint8_t* buffer, int bufferSize) {
FfmpegDecoder* decoder = static_cast<FfmpegDecoder*>(opaque); FfmpegDecoder* decoder = static_cast<FfmpegDecoder*>(opaque);
if (decoder && decoder->Stream()) { if (decoder && decoder->Stream()) {
@ -182,6 +196,9 @@ bool FfmpegDecoder::GetBuffer(IBuffer *buffer) {
return true; return true;
} }
} }
::debug->Warning(TAG, "finished decoding.");
this->exhausted = true;
return false; return false;
} }
@ -214,6 +231,8 @@ void FfmpegDecoder::Reset() {
bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) { bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) {
if (stream->Seekable() && this->ioContext == nullptr) { if (stream->Seekable() && this->ioContext == nullptr) {
::debug->Info(TAG, "parsing data stream...");
this->stream = stream; this->stream = stream;
this->ioContext = avio_alloc_context( this->ioContext = avio_alloc_context(
@ -254,6 +273,7 @@ bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) {
} }
if (this->streamId != -1) { if (this->streamId != -1) {
::debug->Info(TAG, "found audio!");
this->codecContext = this->formatContext->streams[this->streamId]->codec; this->codecContext = this->formatContext->streams[this->streamId]->codec;
if (codecContext) { if (codecContext) {
this->codecContext->request_sample_fmt = AV_SAMPLE_FMT_FLT; this->codecContext->request_sample_fmt = AV_SAMPLE_FMT_FLT;
@ -262,8 +282,10 @@ bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) {
if (avcodec_open2(codecContext, codec, nullptr) < 0) { if (avcodec_open2(codecContext, codec, nullptr) < 0) {
goto reset_and_fail; goto reset_and_fail;
} }
::debug->Info(TAG, "resolved a codec!");
} }
else { else {
::debug->Error(TAG, "couldn't find a codec.");
goto reset_and_fail; goto reset_and_fail;
} }
} }
@ -274,16 +296,20 @@ bool FfmpegDecoder::Open(musik::core::sdk::IDataStream *stream) {
this->duration = (double) this->formatContext->duration / (double) AV_TIME_BASE; this->duration = (double) this->formatContext->duration / (double) AV_TIME_BASE;
return true; return true;
} }
else {
::debug->Error(TAG, "audio stream not found in input data.");
}
} }
} }
} }
} }
reset_and_fail: reset_and_fail:
::debug->Error(TAG, "failed to find compatible audio stream");
this->Reset(); this->Reset();
return false; return false;
} }
bool FfmpegDecoder::Exhausted() { bool FfmpegDecoder::Exhausted() {
return false; return this->exhausted;
} }

View File

@ -80,4 +80,5 @@ class FfmpegDecoder: public musik::core::sdk::IDecoder {
size_t rate, channels; size_t rate, channels;
int streamId; int streamId;
double duration; double duration;
bool exhausted{false};
}; };