From bc6bd8a2b8b84a79dd77b81d6a25b661c5d1d1ca Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sun, 16 Dec 2018 14:14:41 +0100 Subject: Add optional debugging code Compile *without* -DNDEBUG. The environment variable PIANOBAR_DEBUG accepts a bitfield which enables (1) network (2) audio (4) UI debug messages. --- Makefile | 1 + src/config.h | 7 +++++++ src/debug.c | 29 +++++++++++++++++++++++++++ src/debug.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 4 ++++ src/player.c | 17 ++++++++++++++++ src/ui.c | 3 +++ 7 files changed, 125 insertions(+) create mode 100644 src/debug.c create mode 100644 src/debug.h diff --git a/Makefile b/Makefile index 1445575..b4ed0a7 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ endif PIANOBAR_DIR:=src PIANOBAR_SRC:=\ ${PIANOBAR_DIR}/main.c \ + ${PIANOBAR_DIR}/debug.c \ ${PIANOBAR_DIR}/player.c \ ${PIANOBAR_DIR}/settings.c \ ${PIANOBAR_DIR}/terminal.c \ diff --git a/src/config.h b/src/config.h index 48a4cfe..4580f43 100644 --- a/src/config.h +++ b/src/config.h @@ -42,3 +42,10 @@ #define HAVE_AV_REGISTER_ALL #endif +#ifndef NDEBUG +#define HAVE_DEBUGLOG +#define debug(...) fprintf(stderr, __VA_ARGS__) +#else +#define debug(...) +#endif + diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..95ca817 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,29 @@ +/* +Copyright (c) 2008-2018 + Lars-Dominik Braun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "debug.h" + +#ifdef HAVE_DEBUGLOG +unsigned int debug = 0; +#endif + diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..e2e356b --- /dev/null +++ b/src/debug.h @@ -0,0 +1,64 @@ +/* +Copyright (c) 2008-2018 + Lars-Dominik Braun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +#include "config.h" +#include + +#ifdef HAVE_DEBUGLOG +#include +#include +#include + +/* bitfield */ +typedef enum { + DEBUG_NETWORK = 1, + DEBUG_AUDIO = 2, + DEBUG_UI = 4, +} debugKind; + +extern unsigned int debug; + +inline static bool debugEnable () { + const char * const debugStr = getenv("PIANOBAR_DEBUG"); + if (debugStr != NULL) { + debug = atoi (debugStr); + } + return debug; +} + +__attribute__((format(printf, 2, 3))) +inline static void debugPrint(debugKind kind, const char * const format, ...) { + if (debug & kind) { + va_list fmtargs; + va_start (fmtargs, format); + vfprintf (stderr, format, fmtargs); + va_end (fmtargs); + } +} +#else +inline static bool debugEnable () {} +#define debugPrint(...) +#endif + diff --git a/src/main.c b/src/main.c index 6388cde..de09fb7 100644 --- a/src/main.c +++ b/src/main.c @@ -51,6 +51,7 @@ THE SOFTWARE. #include #include "main.h" +#include "debug.h" #include "terminal.h" #include "ui.h" #include "ui_dispatch.h" @@ -401,6 +402,7 @@ sig_atomic_t *interrupted = NULL; static void intHandler (int signal) { if (interrupted != NULL) { + debugPrint(DEBUG_UI, "Received ^C\n"); *interrupted += 1; } } @@ -417,6 +419,8 @@ static void BarMainSetupSigaction () { int main (int argc, char **argv) { static BarApp_t app; + debugEnable(); + memset (&app, 0, sizeof (app)); /* save terminal attributes, before disabling echoing */ diff --git a/src/player.c b/src/player.c index d73b718..b8eeead 100644 --- a/src/player.c +++ b/src/player.c @@ -41,6 +41,7 @@ THE SOFTWARE. #include #include #include +#include #include #include @@ -58,6 +59,7 @@ THE SOFTWARE. #include #include "player.h" +#include "debug.h" #include "ui.h" #include "ui_types.h" @@ -421,6 +423,7 @@ static int play (player_t * const player) { /* enter drain mode */ drainMode = DRAIN; avcodec_send_packet (cctx, NULL); + debugPrint (DEBUG_AUDIO, "decoder entering drain mode after EOF\n"); } else if (pkt.stream_index != player->streamIdx) { /* unused packet */ av_packet_unref (&pkt); @@ -428,6 +431,8 @@ static int play (player_t * const player) { } else if (ret < 0) { /* error, abort */ /* mark the EOF, so that BarAoPlayThread can quit*/ + debugPrint (DEBUG_AUDIO, "av_read_frame failed with code %i, sending " + "NULL frame\n", ret); pthread_mutex_lock (&player->aoplayLock); const int rt = av_buffersrc_add_frame (player->fabuf, NULL); assert (rt == 0); @@ -446,6 +451,7 @@ static int play (player_t * const player) { /* done draining */ drainMode = DONE; /* mark the EOF*/ + debugPrint (DEBUG_AUDIO, "receive_frame got EOF, sending NULL frame\n"); pthread_mutex_lock (&player->aoplayLock); const int rt = av_buffersrc_add_frame (player->fabuf, NULL); assert (rt == 0); @@ -471,10 +477,14 @@ static int play (player_t * const player) { pthread_mutex_lock (&player->aoplayLock); bufferHealth = timeBase * (double) (frame->pts - player->lastTimestamp); if (bufferHealth > minBufferHealth) { + debugPrint (DEBUG_AUDIO, "decoding buffer filled health %"PRIi64" minHealth %"PRIi64"\n", + bufferHealth, minBufferHealth); /* Buffer get healthy, resume */ pthread_cond_broadcast (&player->aoplayCond); /* Buffer is healthy enough, wait */ pthread_cond_wait (&player->aoplayCond, &player->aoplayLock); + debugPrint (DEBUG_AUDIO, "ao play signalled it needs more data health %"PRIi64" minHealth %"PRIi64"\n", + bufferHealth, minBufferHealth); } pthread_mutex_unlock (&player->aoplayLock); } while (bufferHealth > minBufferHealth); @@ -483,6 +493,7 @@ static int play (player_t * const player) { av_packet_unref (&pkt); } av_frame_free (&frame); + debugPrint (DEBUG_AUDIO, "decoder is done, waiting for ao player\n"); pthread_join (aoplaythread, NULL); return ret; @@ -558,9 +569,12 @@ void *BarAoPlayThread (void *data) { if (ret == AVERROR_EOF || shouldQuit (player)) { /* we are done here */ pthread_mutex_unlock (&player->aoplayLock); + debugPrint (DEBUG_AUDIO, "ao player got EOF, exiting\n"); break; } else if (ret < 0) { /* wait for more frames */ + debugPrint (DEBUG_AUDIO, "ao player is waiting for more frames after code %i (%s)\n", + ret, av_err2str (ret)); pthread_cond_broadcast (&player->aoplayCond); pthread_cond_wait (&player->aoplayCond, &player->aoplayLock); pthread_mutex_unlock (&player->aoplayLock); @@ -582,8 +596,10 @@ void *BarAoPlayThread (void *data) { /* pausing */ if (player->doPause) { do { + debugPrint (DEBUG_AUDIO, "ao player is paused\n"); pthread_cond_wait (&player->cond, &player->lock); } while (player->doPause); + debugPrint (DEBUG_AUDIO, "ao player continues\n"); } pthread_mutex_unlock (&player->lock); @@ -599,6 +615,7 @@ void *BarAoPlayThread (void *data) { av_frame_unref (filteredFrame); } av_frame_free (&filteredFrame); + debugPrint (DEBUG_AUDIO, "ao player is done\n"); return (void *) 0; } diff --git a/src/ui.c b/src/ui.c index 6ccc2af..99b74c3 100644 --- a/src/ui.c +++ b/src/ui.c @@ -40,6 +40,7 @@ THE SOFTWARE. #include #include "ui.h" +#include "debug.h" #include "ui_readline.h" typedef int (*BarSortFunc_t) (const void *, const void *); @@ -189,6 +190,7 @@ static CURLcode BarPianoHttpRequest (CURL * const http, req->secure ? settings->rpcTlsPort : "80", req->urlPath); assert (ret >= 0 && ret <= (int) sizeof (url)); + debugPrint (DEBUG_NETWORK, "← %s\n", url); /* save the previous interrupt destination */ prevint = interrupted; @@ -261,6 +263,7 @@ static CURLcode BarPianoHttpRequest (CURL * const http, curl_slist_free_all (list); req->responseData = buffer.data; + debugPrint (DEBUG_NETWORK, "→ %s\n", req->responseData); interrupted = prevint; -- cgit v1.2.3