diff --git a/include/error.h b/include/error.h index 13f59d55..8b9b8591 100644 --- a/include/error.h +++ b/include/error.h @@ -49,42 +49,103 @@ extern "C" { const char *snd_strerror(int errnum); +#define SND_LOG_ERROR 1 /**< error priority level */ +#define SND_LOG_WARN 2 /**< warning priority level */ +#define SND_LOG_INFO 3 /**< info priority level */ +#define SND_LOG_DEBUG 4 /**< debug priority level */ +#define SND_LOG_TRACE 5 /**< trace priority level */ + +#define SND_ILOG_CORE 1 /**< core library code */ +#define SND_ILOG_CONFIG 2 /**< configuration parsing and operations */ +#define SND_ILOG_CONTROL 3 /**< control API */ +#define SND_ILOG_HWDEP 4 /**< hwdep API */ +#define SND_ILOG_TIMER 5 /**< timer API */ +#define SND_ILOG_RAWMIDI 6 /**< RawMidi API */ +#define SND_ILOG_PCM 7 /**< PCM API */ +#define SND_ILOG_MIXER 8 /**< mixer API */ +#define SND_ILOG_SEQUENCER 9 /**< sequencer API */ +#define SND_ILOG_UCM 10 /**< UCM API */ +#define SND_ILOG_TOPOLOGY 11 /**< topology API */ +#define SND_ILOG_ASERVER 12 /**< aserver */ + /** - * \brief Error handler callback. + * \brief Log handler callback. + * \param prio Priority (SND_LOG_* defines). + * \param interface Interface (SND_ILOG_* defines). * \param file Source file name. * \param line Line number. * \param function Function name. - * \param err Value of \c errno, or 0 if not relevant. + * \param errcode Value of \c errno, or 0 if not relevant. * \param fmt \c printf(3) format. * \param ... \c printf(3) arguments. * * A function of this type is called by the ALSA library when an error occurs. * This function usually shows the message on the screen, and/or logs it. */ -typedef void (*snd_lib_error_handler_t)(const char *file, int line, const char *function, int err, const char *fmt, ...) /* __attribute__ ((format (printf, 5, 6))) */; -extern snd_lib_error_handler_t snd_lib_error; -extern int snd_lib_error_set_handler(snd_lib_error_handler_t handler); +typedef void (*snd_lib_log_handler_t)(int prio, int interface, const char *file, int line, const char *function, int errcode, const char *fmt, va_list arg); +extern snd_lib_log_handler_t snd_lib_vlog; +void snd_lib_log(int prio, int interface, const char *file, int line, const char *function, int errcode, const char *fmt, ...) /* __attribute__ ((format (printf, 7, 8))) */; +void snd_lib_check(int interface, const char *file, int line, const char *function, int errcode, const char *fmt, ...); +snd_lib_log_handler_t snd_lib_log_set_handler(snd_lib_log_handler_t handler); +snd_lib_log_handler_t snd_lib_log_set_local(snd_lib_log_handler_t handler); #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) -#define SNDERR(...) snd_lib_error(__FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows a sound error message. */ -#define SYSERR(...) snd_lib_error(__FILE__, __LINE__, __func__, errno, __VA_ARGS__) /**< Shows a system error message (related to \c errno). */ +#define snd_error(interface, ...) snd_lib_log(SND_LOG_ERROR, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an error log message. */ +#define snd_errornum(interface, ...) snd_lib_log(SND_LOG_ERROR, SND_ILOG_##interface, __FILE__, __LINE__, __func__, errno, __VA_ARGS__) /**< Shows a system error log message (related to \c errno). */ +#define snd_warn(interface, ...) snd_lib_log(SND_LOG_WARN, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an error log message. */ +#define snd_info(interface, ...) snd_lib_log(SND_LOG_INFO, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an informational log message. */ +#define snd_debug(interface, ...) snd_lib_log(SND_LOG_DEBUG, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an debug log message. */ +#define snd_trace(interface, ...) snd_lib_log(SND_LOG_TRACE, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an trace log message. */ +#define snd_check(interface, ...) snd_lib_check(SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows an check log message. */ +#define snd_checknum(interface, ...) snd_lib_check(SND_ILOG_##interface, __FILE__, __LINE__, __func__, errno, __VA_ARGS__) /**< Shows an check log message (related to \c errno). */ #else -#define SNDERR(args...) snd_lib_error(__FILE__, __LINE__, __func__, 0, ##args) /**< Shows a sound error message. */ -#define SYSERR(args...) snd_lib_error(__FILE__, __LINE__, __func__, errno, ##args) /**< Shows a system error message (related to \c errno). */ +#define snd_error(interface, args...) snd_lib_log(SND_LOG_ERROR, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an error log message. */ +#define snd_errornum(interface, args...) snd_lib_log(SND_LOG_ERROR, SND_ILOG_##interface, __FILE__, __LINE__, __func__, errno, ##args) /**< Shows a system error log message (related to \c errno). */ +#define snd_warn(interface, args...) snd_lib_log(SND_LOG_WARN, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an error log message. */ +#define snd_info(interface, args...) snd_lib_log(SND_LOG_INFO, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an error log message. */ +#define snd_debug(interface, args...) snd_lib_log(SND_LOG_DEBUG, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an error log message. */ +#define snd_trace(interface, args...) snd_lib_log(SND_LOG_TRACE, SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an trace log message. */ +#define snd_check(interface, args...) snd_lib_check(SND_ILOG_##interface, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows an check log message. */ +#define snd_check(interface, args...) snd_lib_check(SND_ILOG_##interface, __FILE__, __LINE__, __func__, errno, ##args) /**< Shows an check log message (related to \c errno). */ #endif +/** + * \brief Error handler callback. + * \param file Source file name. + * \param line Line number. + * \param function Function name. + * \param errcode Value of \c errno, or 0 if not relevant. + * \param fmt \c printf(3) format. + * \param ... \c printf(3) arguments. + * \deprecated Since 1.2.15 + * + * A function of this type is called by the ALSA library when an error occurs. + * This function usually shows the message on the screen, and/or logs it. + */ +typedef void (*snd_lib_error_handler_t)(const char *file, int line, const char *function, int errcode, const char *fmt, ...) /* __attribute__ ((format (printf, 5, 6))) */; +extern snd_lib_error_handler_t snd_lib_error; +int snd_lib_error_set_handler(snd_lib_error_handler_t handler); + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) +#define SNDERR(...) snd_lib_log(SND_LOG_ERROR, 0, __FILE__, __LINE__, __func__, 0, __VA_ARGS__) /**< Shows a sound error message. */ +#define SYSERR(...) snd_lib_log(SND_LOG_ERROR, 0, __FILE__, __LINE__, __func__, errno, __VA_ARGS__) /**< Shows a system error message (related to \c errno). */ +#else +#define SNDERR(args...) snd_lib_log(SND_LOG_ERROR, 0, __FILE__, __LINE__, __func__, 0, ##args) /**< Shows a sound error message. */ +#define SYSERR(args...) snd_lib_log(SND_LOG_ERROR, 0, __FILE__, __LINE__, __func__, errno, ##args) /**< Shows a system error message (related to \c errno). */ +#endif + +/** Local error handler function type */ +typedef void (*snd_local_error_handler_t)(const char *file, int line, + const char *func, int errcode, + const char *fmt, va_list arg); +snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func); + /** \} */ #ifdef __cplusplus } #endif -/** Local error handler function type */ -typedef void (*snd_local_error_handler_t)(const char *file, int line, - const char *func, int err, - const char *fmt, va_list arg); -snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func); #endif /* __ALSA_ERROR_H */ - diff --git a/include/local.h b/include/local.h index fec332e5..da70cf52 100644 --- a/include/local.h +++ b/include/local.h @@ -274,9 +274,8 @@ size_t snd_strlcat(char *dst, const char *src, size_t size); */ #ifndef NDEBUG #define CHECK_SANITY(x) x -extern snd_lib_error_handler_t _snd_err_msg; -#define SNDMSG(args...) _snd_err_msg(__FILE__, __LINE__, __func__, 0, ##args) -#define SYSMSG(args...) _snd_err_msg(__FILE__, __LINE__, __func__, errno, ##args) +#define SNDMSG(args...) snd_lib_check(0, __FILE__, __LINE__, __func__, 0, ##args) +#define SYSMSG(args...) snd_lib_check(0, __FILE__, __LINE__, __func__, errno, ##args) #else #define CHECK_SANITY(x) 0 /* not evaluated */ #define SNDMSG(args...) /* nop */ diff --git a/src/Versions.in.in b/src/Versions.in.in index 4aa2e13b..36b6ab5d 100644 --- a/src/Versions.in.in +++ b/src/Versions.in.in @@ -214,3 +214,16 @@ ALSA_1.2.13 { @SYMBOL_PREFIX@snd_ump_packet_length; #endif } ALSA_1.2.10; + + +ALSA_1.2.15 { + global: + + @SYMBOL_PREFIX@snd_lib_vlog; + @SYMBOL_PREFIX@snd_lib_log; + @SYMBOL_PREFIX@snd_lib_log_set_handler; + @SYMBOL_PREFIX@snd_lib_log_set_local; + @SYMBOL_PREFIX@snd_lib_log_priority; + @SYMBOL_PREFIX@snd_lib_log_interface; + @SYMBOL_PREFIX@snd_lib_check; +} ALSA_1.2.13; diff --git a/src/conf.c b/src/conf.c index 91aa628b..92446e61 100644 --- a/src/conf.c +++ b/src/conf.c @@ -811,7 +811,7 @@ static int get_char_skip_comments(input_t *input) dirp = opendir(str); if (!dirp) { - SNDERR("Invalid search dir %s", str); + snd_error(CONFIG, "Invalid search dir %s", str); free(str); return -EINVAL; } diff --git a/src/control/namehint.c b/src/control/namehint.c index 11783c0c..8d6c64d5 100644 --- a/src/control/namehint.c +++ b/src/control/namehint.c @@ -104,7 +104,9 @@ static int hint_list_add_custom(struct hint_list *list, return err; } -static void zero_handler(const char *file ATTRIBUTE_UNUSED, +static void zero_handler(int prio ATTRIBUTE_UNUSED, + int interface ATTRIBUTE_UNUSED, + const char *file ATTRIBUTE_UNUSED, int line ATTRIBUTE_UNUSED, const char *function ATTRIBUTE_UNUSED, int err ATTRIBUTE_UNUSED, @@ -239,7 +241,7 @@ static int try_config(snd_config_t *config, const char *base, const char *name) { - snd_local_error_handler_t eh; + snd_lib_log_handler_t eh; snd_config_t *res = NULL, *cfg, *cfg1, *n; snd_config_iterator_t i, next; char *buf, *buf1 = NULL, *buf2; @@ -266,9 +268,9 @@ static int try_config(snd_config_t *config, sprintf(buf, "%s:CARD=%s", name, snd_ctl_card_info_get_id(list->info)); else strcpy(buf, name); - eh = snd_lib_error_set_local(&zero_handler); + eh = snd_lib_log_set_local(&zero_handler); err = snd_config_search_definition(config, base, buf, &res); - snd_lib_error_set_local(eh); + snd_lib_log_set_local(eh); if (err < 0) goto __skip_add; cleanup_res = 1; @@ -369,9 +371,9 @@ static int try_config(snd_config_t *config, goto __ok; /* find, if all parameters have a default, */ /* otherwise filter this definition */ - eh = snd_lib_error_set_local(&zero_handler); + eh = snd_lib_log_set_local(&zero_handler); err = snd_config_search_alias_hooks(config, base, buf, &res); - snd_lib_error_set_local(eh); + snd_lib_log_set_local(eh); if (err < 0) goto __cleanup; if (snd_config_search(res, "@args", &cfg) >= 0) { diff --git a/src/error.c b/src/error.c index 0eefce0e..e077cb95 100644 --- a/src/error.c +++ b/src/error.c @@ -68,47 +68,100 @@ const char *snd_strerror(int errnum) #endif #endif +static TLS_PFX snd_lib_log_handler_t local_log = NULL; static TLS_PFX snd_local_error_handler_t local_error = NULL; /** - * \brief Install local error handler - * \param func The local error handler function - * \retval Previous local error handler function + * \brief Install local log handler + * \param func The local log handler function + * \retval Previous local log handler function */ -snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func) +snd_lib_log_handler_t snd_lib_log_set_local(snd_lib_log_handler_t func) { - snd_local_error_handler_t old = local_error; - local_error = func; + snd_lib_log_handler_t old = local_log; + local_log = func; return old; } /** - * \brief The default error handler function. + * \brief The default log handler function. + * \param prio Priority value (SND_LOG_*). + * \param interface Interface (SND_ILOG_*). * \param file The filename where the error was hit. * \param line The line number. * \param function The function name. - * \param err The error code. + * \param errcode The error code. * \param fmt The message (including the format characters). * \param ... Optional arguments. * * If a local error function has been installed for the current thread by - * \ref snd_lib_error_set_local, it is called. Otherwise, prints the error + * \ref snd_lib_log_set_local, it is called. Otherwise, prints the error * message including location to \c stderr. */ -static void snd_lib_error_default(const char *file, int line, const char *function, int err, const char *fmt, ...) +static void snd_lib_vlog_default(int prio, int interface, const char *file, int line, const char *function, int errcode, const char *fmt, va_list arg) { - va_list arg; - va_start(arg, fmt); - if (local_error) { - local_error(file, line, function, err, fmt, arg); - va_end(arg); + if (local_log) { + local_log(prio, interface, file, line, function, errcode, fmt, arg); + return; + } + if (local_error && prio == SND_LOG_ERROR) { + local_error(file, line, function, errcode, fmt, arg); return; } fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); vfprintf(stderr, fmt, arg); - if (err) - fprintf(stderr, ": %s", snd_strerror(err)); + if (errcode) + fprintf(stderr, ": %s", snd_strerror(errcode)); putc('\n', stderr); +} + +/** + * \brief Root log handler function. + * \param prio Priority value (SND_LOG_*). + * \param interface Interface (SND_ILOG_*). + * \param file The filename where the error was hit. + * \param line The line number. + * \param function The function name. + * \param errcode The error code. + * \param fmt The message (including the format characters). + * \param ... Optional arguments. + */ +void snd_lib_log(int prio, int interface, const char *file, int line, const char *function, int errcode, const char *fmt, ...) +{ + va_list arg; + va_start(arg, fmt); + snd_lib_vlog(prio, interface, file, line, function, errcode, fmt, arg); + va_end(arg); +} + +/** + * \brief The check point function. + * \param interface Interface (SND_ILOG_*). + * \param file The filename where the error was hit. + * \param line The line number. + * \param function The function name. + * \param errcode The error code. + * \param fmt The message (including the format characters). + * \param ... Optional arguments. + * + * The error message is passed with error priority level to snd_lib_vlog handler. + */ +void snd_lib_check(int interface, const char *file, int line, const char *function, int errcode, const char *fmt, ...) +{ + const char *verbose; + + va_list arg; + va_start(arg, fmt); + verbose = getenv("LIBASOUND_DEBUG"); + if (! verbose || ! *verbose) + goto finish; + snd_lib_vlog(SND_LOG_ERROR, interface, file, line, function, errcode, fmt, arg); +#ifdef ALSA_DEBUG_ASSERT + verbose = getenv("LIBASOUND_DEBUG_ASSERT"); + if (verbose && *verbose) + assert(0); +#endif +finish: va_end(arg); } @@ -117,11 +170,71 @@ static void snd_lib_error_default(const char *file, int line, const char *functi * Pointer to the error handler function. * For internal use only. */ +snd_lib_log_handler_t snd_lib_vlog = snd_lib_vlog_default; + +/** + * \brief Sets the log handler. + * \param handler The pointer to the new log handler function. + * \retval Previous log handler function + * + * This function sets a new log handler, or (if \c handler is \c NULL) + * the default one which prints the error messages to \c stderr. + */ +snd_lib_log_handler_t snd_lib_log_set_handler(snd_lib_log_handler_t handler) +{ + snd_lib_log_handler_t old = snd_lib_vlog; + snd_lib_vlog = handler == NULL ? snd_lib_vlog_default : handler; + return old; +} + + +/** + * \brief Install local error handler + * \param func The local error handler function + * \retval Previous local error handler function + * \deprecated Since 1.2.15 + */ +snd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func) +{ + snd_local_error_handler_t old = local_error; + local_error = func; + return old; +} +link_warning(snd_lib_error_set_local, "Warning: snd_lib_error_set_local is deprecated, use snd_lib_log_set_local"); + +/** + * \brief The default error handler function. + * \param file The filename where the error was hit. + * \param line The line number. + * \param function The function name. + * \param errcode The error code. + * \param fmt The message (including the format characters). + * \param ... Optional arguments. + * \deprecated Since 1.2.15 + * + * Use snd_lib_vlog handler to print error message for anonymous interface. + */ +static void snd_lib_error_default(const char *file, int line, const char *function, int errcode, const char *fmt, ...) +{ + va_list arg; + va_start(arg, fmt); + snd_lib_vlog(SND_LOG_ERROR, 0, file, line, function, errcode, fmt, arg); + va_end(arg); +} + +/** + * \ingroup Error + * \deprecated Since 1.2.15 + * Pointer to the error handler function. + * For internal use only. + */ snd_lib_error_handler_t snd_lib_error = snd_lib_error_default; +link_warning(snd_lib_error, "Warning: snd_lib_error is deprecated, use snd_log interface"); /** * \brief Sets the error handler. * \param handler The pointer to the new error handler function. + * \deprecated Since 1.2.15 * * This function sets a new error handler, or (if \c handler is \c NULL) * the default one which prints the error messages to \c stderr. @@ -129,10 +242,6 @@ snd_lib_error_handler_t snd_lib_error = snd_lib_error_default; int snd_lib_error_set_handler(snd_lib_error_handler_t handler) { snd_lib_error = handler == NULL ? snd_lib_error_default : handler; -#ifndef NDEBUG - if (snd_lib_error != snd_lib_error_default) - _snd_err_msg = snd_lib_error; -#endif return 0; } @@ -145,39 +254,6 @@ const char *snd_asoundlib_version(void) return SND_LIB_VERSION_STR; } -#ifndef NDEBUG -/* - * internal error handling - */ -static void snd_err_msg_default(const char *file, int line, const char *function, int err, const char *fmt, ...) -{ - va_list arg; - const char *verbose; - - verbose = getenv("LIBASOUND_DEBUG"); - if (! verbose || ! *verbose) - return; - va_start(arg, fmt); - fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); - vfprintf(stderr, fmt, arg); - if (err) - fprintf(stderr, ": %s", snd_strerror(err)); - putc('\n', stderr); - va_end(arg); -#ifdef ALSA_DEBUG_ASSERT - verbose = getenv("LIBASOUND_DEBUG_ASSERT"); - if (verbose && *verbose) - assert(0); -#endif -} - -/** - * The ALSA error message handler - */ -snd_lib_error_handler_t _snd_err_msg = snd_err_msg_default; - -#endif - /** * \brief Copy a C-string into a sized buffer * \param dst Where to copy the string to